readlink
Overview
The readlink
command displays the target of symbolic links. It resolves symbolic links and shows where they point, essential for understanding link structures and debugging link issues.
Syntax
readlink [options] file...
Common Options
Option | Description |
---|---|
-f |
Follow all symbolic links |
-e |
All components must exist |
-m |
No components need exist |
-n |
Don’t output trailing newline |
-q |
Suppress error messages |
-s |
Suppress non-error messages |
-v |
Verbose output |
-z |
End output with null character |
Key Use Cases
- Display symbolic link targets
- Resolve link chains
- Debug broken links
- Script path resolution
- Link validation
Examples with Explanations
Example 1: Basic Usage
readlink symlink
Shows where the symbolic link points
Example 2: Follow All Links
readlink -f symlink
Resolves all symbolic links in the path
Example 3: Canonical Path
readlink -e /usr/bin/python
Shows canonical path, fails if target doesn’t exist
Example 4: Multiple Files
readlink -f link1 link2 link3
Resolves multiple symbolic links
Link Resolution
Single level:
readlink symlink
Full resolution:
readlink -f symlink
Existing files only:
readlink -e symlink
Common Usage Patterns
Check if file is a link:
if readlink "$file" >/dev/null 2>&1; then echo "$file is a symbolic link" fi
Get script directory:
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
Resolve configuration files:
CONFIG_FILE=$(readlink -f ~/.config/app.conf)
Script Applications
Portable script paths:
#!/bin/bash SCRIPT_PATH=$(readlink -f "$0") SCRIPT_DIR=$(dirname "$SCRIPT_PATH") cd "$SCRIPT_DIR"
Link validation:
validate_link() { local link="$1" if ! readlink -e "$link" >/dev/null 2>&1; then echo "Broken link: $link" return 1 fi }
Performance Analysis
- Fast operation
- No file content reading
- Minimal system resources
- Good for path resolution
- Efficient link checking
Best Practices
- Use -f for complete resolution
- Check if target exists with -e
- Handle broken links gracefully
- Use in scripts for portability
- Combine with other path tools
Error Handling
Broken links:
if ! readlink -e "$link" >/dev/null 2>&1; then echo "Link is broken or doesn't exist" fi
Not a symbolic link:
target=$(readlink "$file" 2>/dev/null) || { echo "$file is not a symbolic link" }
Integration Examples
Find broken links:
find /path -type l | while read link; do if ! readlink -e "$link" >/dev/null 2>&1; then echo "Broken: $link" fi done
Link maintenance:
for link in *.link; do target=$(readlink "$link") echo "$link -> $target" done
Advanced Usage
Quiet operation:
readlink -q symlink
No trailing newline:
readlink -n symlink
Null-terminated output:
readlink -z symlink
Troubleshooting
- Permission denied errors
- Broken symbolic links
- Circular link references
- Non-existent targets
- Cross-filesystem links
Security Considerations
- Validate link targets
- Check for directory traversal
- Verify link ownership
- Monitor link changes
- Handle untrusted links carefully
Alternative Methods
Using ls:
ls -l symlink | awk '{print $NF}'
Using stat:
stat -c %N symlink
Using file:
file symlink
Real-world Examples
System administration:
# Check system links readlink /usr/bin/java readlink /etc/alternatives/editor
Development workflow:
# Resolve project paths PROJECT_ROOT=$(readlink -f "$(dirname "$0")/..")
Configuration management:
# Verify config links for config in /etc/*.conf; do if [ -L "$config" ]; then echo "$config -> $(readlink "$config")" fi done