Bash by Example: Batch Rename Files
Mass renaming files using string manipulation and loops for bulk file operations, implementing pattern-based renaming with parameter expansion, changing file extensions across multiple files, adding prefixes or suffixes systematically, and performing complex filename transformations without external tools.
Code
#!/bin/bash
# Setup dummy files
mkdir -p photos
touch photos/img_001.jpg photos/img_002.jpg photos/img_003.png
echo "Original files:"
ls photos
echo -e "\nRenaming .jpg to .jpeg..."
for file in photos/*.jpg; do
# Check if file exists (in case glob matches nothing)
[ -e "$file" ] || continue
# String Manipulation
# ${var%pattern} removes shortest match from END
base_name="${file%.jpg}"
# Construct new name
new_name="${base_name}.jpeg"
mv "$file" "$new_name"
echo "Renamed: $file -> $new_name"
done
echo -e "\nAdding prefix 'vacation_'..."
for file in photos/*; do
# Get just the filename without path
filename=$(basename "$file")
dir=$(dirname "$file")
mv "$file" "$dir/vacation_$filename"
done
echo -e "\nFinal files:"
ls photos
rm -rf photosExplanation
Renaming a single file is easy with mv, but renaming hundreds of files—changing extensions, adding dates, or fixing capitalization—requires automation. While there is a dedicated rename utility (Perl-based) on many systems, it is not standard everywhere. Bash's built-in string manipulation capabilities allow you to write portable batch rename scripts without external dependencies.
The key feature here is Parameter Expansion. The syntax ${variable%pattern} removes the shortest match of pattern from the end of the variable. For example, if file="image.jpg", then ${file%.jpg} evaluates to "image". This allows you to strip the old extension and append a new one.
Another common requirement is adding a prefix. This involves separating the directory path from the filename using dirname and basename (or more parameter expansion), modifying the filename string, and then reassembling the path for the mv command.
Code Breakdown
${file%.jpg} is a standard Bash string operation. It strips the suffix ".jpg". If the variable doesn't end with that pattern, it remains unchanged.basename and dirname are essential when looping over globs like dir/*. The variable $file contains the full path photos/img.jpg. We need to split it to rename just the file part, not the directory part.
