Command documentation sourced from the linux-command project This comprehensive command reference is part of the linux-command documentation project.
basename - Remove directory suffix from filenames
The basename command is a fundamental utility that strips directory components from file paths, returning only the filename component. It's essential for shell scripting, file processing, and path manipulation tasks. The command can also remove specified suffixes from filenames, making it particularly useful for extracting file extensions or processing filenames in batch operations.
Basic Syntax
basename NAME [SUFFIX]
basename OPTION... NAME...
Common Options
-a, --multiple- Support multiple arguments and treat each as a NAME-s, --suffix=SUFFIX- Remove a trailing SUFFIX-z, --zero- Separate output with NUL characters instead of newlines--help- Display help information--version- Show version information
Usage Examples
Basic Path Operations
Extracting Filenames
# Extract filename from full path
basename /home/user/documents/report.pdf
# Output: report.pdf
# Extract filename from current directory path
basename ./script.sh
# Output: script.sh
# Handle relative paths
basename ../data/config.json
# Output: config.json
# Extract filename from absolute path
basename /var/log/system.log
# Output: system.log
# Handle paths with trailing slash
basename /path/to/directory/
# Output: directory
# Complex nested paths
basename /very/deep/nested/directory/structure/file.txt
# Output: file.txt
Removing Suffixes
# Remove file extension
basename /home/user/document.pdf .pdf
# Output: document
# Remove multiple extensions
basename archive.tar.gz .tar.gz
# Output: archive
# Remove custom suffix
basename backup_20231201.tar.gz _20231201.tar.gz
# Output: backup
# Remove version suffix
basename application-v2.1.0.zip -v2.1.0.zip
# Output: application
# Remove prefix suffix
basename file_backup.txt _backup.txt
# Output: file
# Handle paths without specified suffix
basename /path/to/file.txt .pdf
# Output: file.txt (suffix not found, returns original)
Multiple File Processing
Processing Multiple Paths
# Process multiple files at once
basename -a /path/to/file1.txt /path/to/file2.txt /path/to/file3.txt
# Output:
# file1.txt
# file2.txt
# file3.txt
# Remove suffix from multiple files
basename -a -s .txt document.txt report.txt summary.txt
# Output:
# document
# report
# summary
# Process paths with different directories
basename -a /home/user/file1.txt /var/log/file2.log /tmp/file3.tmp
# Output:
# file1.txt
# file2.log
# file3.tmp
# Handle multiple files with same suffix
basename -a -s .log access.log error.log debug.log
# Output:
# access
# error
# debug
# Mixed path operations
basename -a /absolute/path/file.txt ./relative/path/file.txt file.txt
# Output:
# file.txt
# file.txt
# file.txt
Zero-Terminated Output
# Use NUL termination for processing special filenames
basename -a -z "file with spaces.txt" "file-with-newline.txt"
# Output: file with spaces.txtfile-with-newline.txt (NUL separated)
# Combine with find command
find /data -name "*.pdf" -exec basename -a -z {} + | xargs -0 -I {} process_file {}
# Process filenames containing newlines or special characters
printf "file\nname.txt\0file\tname.txt\0" | xargs -0 basename -a -z
Practical Examples
Shell Scripting
File Processing Scripts
#!/bin/bash
# Batch file renaming script
for file in *.jpg; do
# Get filename without extension
name=$(basename "$file" .jpg)
# Create new filename with timestamp
new_name="${name}_$(date +%Y%m%d).jpg"
# Rename file
mv "$file" "$new_name"
echo "Renamed $file to $new_name"
done
# Process files in subdirectories
find /source -type f -name "*.log" | while read -r filepath; do
filename=$(basename "$filepath")
cp "$filepath" "/destination/$filename"
done
Path Manipulation
#!/bin/bash
# Extract directory and filename from paths
full_path="/home/user/documents/reports/annual_report_2023.pdf"
# Get directory and filename
directory=$(dirname "$full_path")
filename=$(basename "$full_path")
echo "Directory: $directory"
echo "Filename: $filename"
# Get filename without extension
name_without_ext=$(basename "$full_path" .pdf)
echo "Name without extension: $name_without_ext"
# Extract file extension
extension="${filename##*.}"
echo "Extension: $extension"
Backup and Archive Scripts
#!/bin/bash
# Create backup with original filename structure
SOURCE_DIR="/home/user/documents"
BACKUP_DIR="/backups/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
# Find all PDF files and create backup with original names
find "$SOURCE_DIR" -name "*.pdf" | while read -r filepath; do
filename=$(basename "$filepath")
cp "$filepath" "$BACKUP_DIR/$filename"
echo "Backed up: $filename"
done
# Create compressed archive with date prefix
archive_name="backup_$(date +%Y%m%d).tar.gz"
cd "$BACKUP_DIR"
tar -czf "../$archive_name" .
System Administration
Log File Management
#!/bin/bash
# Log rotation and management script
LOG_DIR="/var/log"
ARCHIVE_DIR="/var/log/archive"
RETENTION_DAYS=30
mkdir -p "$ARCHIVE_DIR"
# Process log files for archiving
find "$LOG_DIR" -name "*.log.*" -mtime +1 | while read -r logfile; do
filename=$(basename "$logfile")
compressed_file="$ARCHIVE_DIR/${filename}.gz"
# Compress and move log file
gzip -c "$logfile" > "$compressed_file"
if [ $? -eq 0 ]; then
rm "$logfile"
echo "Archived: $filename"
fi
done
# Clean up old archives
find "$ARCHIVE_DIR" -name "*.gz" -mtime +$RETENTION_DAYS -delete
Configuration File Processing
#!/bin/bash
# Configuration backup and validation
CONFIG_DIR="/etc/myapp"
BACKUP_DIR="/etc/myapp/backup"
mkdir -p "$BACKUP_DIR"
# Backup configuration files
for config_file in "$CONFIG_DIR"/*.conf; do
if [ -f "$config_file" ]; then
filename=$(basename "$config_file")
backup_file="$BACKUP_DIR/${filename}.backup.$(date +%Y%m%d_%H%M%S)"
cp "$config_file" "$backup_file"
echo "Backed up: $filename"
fi
done
# Validate configuration files
find "$CONFIG_DIR" -name "*.conf" | while read -r config; do
filename=$(basename "$config")
# Check configuration syntax
if validate_config "$config"; then
echo "✓ $filename is valid"
else
echo "✗ $filename has errors"
fi
done
Development Workflow
Build and Deployment Scripts
#!/bin/bash
# Build script with filename processing
PROJECT_DIR="/home/user/myproject"
BUILD_DIR="$PROJECT_DIR/build"
DIST_DIR="$PROJECT_DIR/dist"
mkdir -p "$BUILD_DIR" "$DIST_DIR"
# Process source files
find "$PROJECT_DIR/src" -name "*.c" | while read -r source_file; do
source_name=$(basename "$source_file" .c)
object_file="$BUILD_DIR/${source_name}.o"
# Compile source file
gcc -c "$source_file" -o "$object_file"
if [ $? -eq 0 ]; then
echo "Compiled: $source_name.c"
else
echo "Failed to compile: $source_name.c"
exit 1
fi
done
# Create distribution package
cd "$PROJECT_DIR"
tar -czf "dist/myproject-$(date +%Y%m%d).tar.gz" src/ Makefile README.md
File Conversion Scripts
#!/bin/bash
# Image batch conversion script
SOURCE_DIR="/path/to/images"
OUTPUT_DIR="/path/to/converted"
mkdir -p "$OUTPUT_DIR"
# Convert all PNG files to JPG
find "$SOURCE_DIR" -name "*.png" | while read -r png_file; do
png_name=$(basename "$png_file" .png)
jpg_file="$OUTPUT_DIR/${png_name}.jpg"
# Convert PNG to JPG
convert "$png_file" -quality 90 "$jpg_file"
if [ $? -eq 0 ]; then
echo "Converted: $png_name.png → $png_name.jpg"
fi
done
# Process image resizing
find "$OUTPUT_DIR" -name "*.jpg" | while read -r jpg_file; do
jpg_name=$(basename "$jpg_file" .jpg)
thumbnail="$OUTPUT_DIR/${jpg_name}_thumb.jpg"
# Create thumbnail
convert "$jpg_file" -thumbnail 150x150 "$thumbnail"
echo "Created thumbnail: ${jpg_name}_thumb.jpg"
done
Advanced Usage
Complex Path Processing
Nested Directory Operations
#!/bin/bash
# Process files from multiple nested directories
declare -A file_extensions
# Process all files and count extensions
find /data -type f | while read -r filepath; do
filename=$(basename "$filepath")
extension="${filename##*.}"
# Count file types
((file_extensions["$extension"]++))
# Create organized directory structure
target_dir="/organized/$extension"
mkdir -p "$target_dir"
# Copy file to organized directory
cp "$filepath" "$target_dir/$filename"
done
# Report file statistics
echo "File extension statistics:"
for ext in "${!file_extensions[@]}"; do
echo "$ext: ${file_extensions[$ext]} files"
done
Path Sanitization
#!/bin/bash
# Sanitize filenames by removing special characters
sanitize_filename() {
local filename="$1"
# Remove directory path
local basename_only=$(basename "$filename")
# Remove spaces and special characters
local sanitized=$(echo "$basename_only" | tr ' ' '_' | tr -d '[:punct:]')
echo "$sanitized"
}
# Process files in directory
for file in "/data/files with spaces"/*; do
if [ -f "$file" ]; then
original_name=$(basename "$file")
new_name=$(sanitize_filename "$file")
if [ "$original_name" != "$new_name" ]; then
mv "$file" "/data/files with spaces/$new_name"
echo "Renamed: $original_name → $new_name"
fi
fi
done
Integration with Other Commands
Pipeline Processing
# Combine with find for complex file operations
find /home -name "*.tmp" -exec basename {} + | sort | uniq -c | sort -nr
# Process file lists
cat file_list.txt | xargs -I {} basename {} | while read filename; do
echo "Processing: $filename"
done
# Create file statistics
find /var/log -type f | xargs basename -a | sort | uniq -c | sort -nr
# Find duplicate filenames
find /data -type f | xargs basename -a | sort | uniq -d
# Count files by extension
find /usr -type f -name "*.so" | xargs basename -a | wc -l
Complex Script Integration
#!/bin/bash
# Advanced file processing with basename
process_directory() {
local target_dir="$1"
local output_file="$2"
echo "Processing directory: $target_dir" | tee -a "$output_file"
# Get directory statistics
local file_count=$(find "$target_dir" -type f | wc -l)
local dir_count=$(find "$target_dir" -type d | wc -l)
echo "Files: $file_count" | tee -a "$output_file"
echo "Directories: $dir_count" | tee -a "$output_file"
# List all files with their basenames
echo -e "\nFile listing:" | tee -a "$output_file"
find "$target_dir" -type f | head -20 | while read -r filepath; do
local filename=$(basename "$filepath")
local size=$(stat -f%z "$filepath" 2>/dev/null || stat -c%s "$filepath" 2>/dev/null || echo "unknown")
echo " $filename ($size bytes)" | tee -a "$output_file"
done
# Extension analysis
echo -e "\nFile extensions:" | tee -a "$output_file"
find "$target_dir" -type f | xargs basename -a | \
sed 's/.*\.//' | sort | uniq -c | sort -nr | head -10 | \
while read count ext; do
echo " .$ext: $count files" | tee -a "$output_file"
done
}
# Process multiple directories
for dir in /home/user /var/log /tmp; do
if [ -d "$dir" ]; then
process_directory "$dir" "directory_analysis.txt"
fi
done
Performance and Optimization
Efficient Batch Processing
#!/bin/bash
# Optimized batch processing
# Use arrays for better performance
files=($(find /source -name "*.txt" -maxdepth 1))
# Process in batches to avoid memory issues
batch_size=100
total_files=${#files[@]}
for ((i=0; i<total_files; i+=batch_size)); do
batch=("${files[@]:i:batch_size}")
# Process batch efficiently
printf '%s\n' "${batch[@]}" | xargs -P 4 -I {} basename {}
done
# Use parallel processing with GNU parallel
find /data -type f | parallel basename {}
Memory-Efficient Processing
#!/bin/bash
# Process large file lists without loading everything into memory
process_large_directory() {
local directory="$1"
# Process files one by one using find with -exec
find "$directory" -type f -print0 | while IFS= read -r -d '' filepath; do
local filename=$(basename "$filepath")
# Process file (example: check file size)
if [ -s "$filepath" ]; then
echo "Processing: $filename"
# Add your processing logic here
fi
done
}
# Use streaming for very large datasets
find /very/large/directory -type f -print0 | \
xargs -0 -P 8 -I {} bash -c 'filename=$(basename "$1"); echo "Found: $filename"' _ {}
Troubleshooting
Common Issues
Handling Special Characters
# Filenames with spaces and special characters
filename_with_spaces="file with spaces.txt"
basename "$filename_with_spaces"
# Correct output: file with spaces.txt
# Avoid word splitting issues
# WRONG: basename file with spaces.txt
# RIGHT: basename "file with spaces.txt"
# Handle newlines in filenames
printf "file\nname.txt\0" | xargs -0 basename -a
# Process filenames with quotes
basename 'file"with"quotes.txt'
Path Edge Cases
# Handle empty paths
basename ""
# Output: (empty string)
# Handle root directory
basename /
# Output: /
# Handle paths ending with dot
basename /path/to/file.
# Output: file.
# Handle hidden files
basename /path/to/.hidden
# Output: .hidden
# Handle paths without directory components
basename just_filename.txt
# Output: just_filename.txt
Cross-Platform Compatibility
# Check basename version and features
basename --version
# Test functionality before using in scripts
if basename "/test/path/file.txt" | grep -q "file.txt"; then
echo "basename working correctly"
else
echo "basename not working as expected"
fi
# Use portable constructs
# Instead of complex bash arrays, use find with -exec
find /path -name "*.txt" -exec basename {} \;
Debugging Techniques
#!/bin/bash
# Debug basename operations
debug_basename() {
local input="$1"
local suffix="$2"
echo "Input: '$input'"
echo "Suffix: '$suffix'"
if [ -n "$suffix" ]; then
result=$(basename "$input" "$suffix")
else
result=$(basename "$input")
fi
echo "Result: '$result'"
echo "---"
}
# Test various inputs
debug_basename "/path/to/file.txt"
debug_basename "/path/to/file.txt" ".txt"
debug_basename "relative/path/file.txt"
debug_basename "./file.txt"
debug_basename "file.txt"
Related Commands
dirname- Extract directory component from pathrealpath- Get absolute pathreadlink- Resolve symbolic linkspathchk- Check file names for validitystat- Display file statusfind- Find files and directoriesxargs- Build and execute command linessed- Stream editor for text processing
Best Practices
- Always quote variables containing paths to handle spaces and special characters
- Use
basename -afor processing multiple files efficiently - Combine with
findfor complex directory processing tasks - Test edge cases when writing scripts that handle user input
- Use
-zoption when processing filenames that might contain newlines - Check command availability and version in portable scripts
- Handle empty or null inputs gracefully in production scripts
- Use
dirnametogether withbasenamefor complete path manipulation - Validate input paths before processing to avoid errors
- Consider using parameter expansion in bash for simple filename operations
Performance Tips
- Use
basename -ainstead of calling basename multiple times in loops - Leverage shell parameter expansion for simple filename operations (faster than external commands)
- Process files in batches when dealing with large numbers of files
- Use
find -exec basename {} +for better performance with many files - Avoid unnecessary subshells when processing filenames
- Use arrays to store filenames when memory allows
- Consider parallel processing with
xargs -Pfor CPU-intensive operations - Minimize I/O operations by processing files in logical groups
The basename command is an essential utility for path manipulation and file processing in shell scripts. While seemingly simple, it's a powerful tool that, when combined with other utilities, enables sophisticated file and directory operations essential for system administration, development workflows, and automation tasks.