Batch Rename Utility in Bash Using Loops
Introduction
Renaming multiple files manually is tedious and error-prone — especially when dealing with large sets of images, logs, or exported data. Bash scripting provides an efficient way to automate this process using loops. In this article, we’ll build a small yet powerful batch rename utility in Bash, discuss patterns for safe and flexible operations, and explore tips to handle performance and edge cases.
1. Listing and Iterating Through Files
The first step to batch renaming is to list the target files and iterate through them using a Bash loop. You can use a standard for loop to process each file one by one.
#!/bin/bash
# List all .jpg files in the current directory
for file in *.jpg; do
echo "Processing: $file"
done
This structure reads every .jpg file from the current directory and prints its name. Later, we’ll replace the echo with logic to rename files. This pattern is generalizable to any file type — just change the *.jpg filter.
Why loops work well: Bash loops handle file globbing efficiently and can easily incorporate conditional logic or string manipulation per filename.
2. Renaming Files with the mv Command
Renaming files is straightforward using the mv (move) command. You just need to define the new file name pattern. Here’s a simple example adding a _backup suffix to every file:
#!/bin/bash
for file in *.log; do
new_name="${file%.log}_backup.log"
echo "Renaming $file to $new_name"
mv "$file" "$new_name"
done
Explanation: The syntax ${file%.log} uses Bash parameter expansion to remove the .log extension temporarily, then reattaches it with a new suffix. This method avoids invoking external commands like cut or awk, improving performance.
3. Adding Sequential Numbers or Dates
Sometimes you may need to add sequence numbers or date stamps to filenames, such as for sorting or versioning. Bash makes this simple using variables and arithmetic.
#!/bin/bash
count=1
for file in *.jpg; do
new_name="photo_$(printf '%03d' $count).jpg"
echo "Renaming $file to $new_name"
mv "$file" "$new_name"
((count++))
done
How it works: The loop initializes a counter at 1 and increments with each iteration. The printf '%03d' ensures a fixed-width number padded with zeros (e.g. 001, 002). This makes the files well sorted even in lexicographical order.
Real-world use case: This is ideal for renaming a batch of camera images or reports exported from systems that have ambiguous filenames.
4. Safer Renaming With Dry Runs and Backup
Always test before renaming hundreds of files. A dry-run approach helps prevent accidents. Instead of immediately applying mv, print the rename commands first.
#!/bin/bash
for file in *.txt; do
new_name="${file%.txt}_archived.txt"
echo "mv \"$file\" \"$new_name\""
done
This prints all intended rename commands without execution. Once you verify them, remove echo to run the rename.
Backup tip: Before executing massive renames, use cp in a loop to copy files to a temporary folder for safety:
mkdir backup_files
for file in *.txt; do
cp "$file" backup_files/
done
This ensures an easy rollback if something goes wrong.
5. Advanced Pattern Renaming Using sed or awk
For complex renaming (like converting spaces to underscores or changing case), you can integrate Bash loops with text utilities such as sed or awk.
#!/bin/bash
for file in *; do
# Replace spaces with underscores
new_name=$(echo "$file" | sed 's/ /_/g')
# Convert uppercase to lowercase
new_name=$(echo "$new_name" | awk '{print tolower($0)}')
if [[ "$file" != "$new_name" ]]; then
echo "Renaming '$file' to '$new_name'"
mv "$file" "$new_name"
fi
done
Explanation: This script sanitizes filenames for safer use in command-line environments by replacing spaces and normalizing the case. The condition check ensures we only rename files whose names actually change, preventing redundant mv operations.
Performance note: For large directories, it’s better to use find combined with -exec for parallel operations or ensure minimal subshell invocations to save time.
Conclusion
Batch renaming with Bash loops is an essential automation trick for developers, sysadmins, and data wranglers. From simple suffix additions to pattern-based transformations, Bash gives you concise, scriptable control over bulk file operations. Always test your scripts with dry runs and backups to maintain data safety. With the techniques covered here, you can create customizable renaming utilities suited for almost any workflow.
Useful links:

