Batch Rename Files by Replacing Patterns in Filenames: A Shell Scripting Guide for Developers


2 views

html

Every developer encounters this situation: You have a collection of files with a consistent naming pattern that needs modification. In our case, we need to rename multiple music files by replacing "ACDC" with "AC-DC" in all filenames within a directory.

Here are three effective approaches using standard Unix/Linux tools:

Method 1: Using rename (Perl variant)

rename 's/ACDC/AC-DC/' *.xxx

Method 2: Using mmv (for more complex patterns)

mmv 'ACDC*' 'AC-DC#1'

Method 3: Using bash parameter expansion

for file in ACDC*.xxx; do
    mv "$file" "${file/ACDC/AC-DC}"
done

The rename Command

The Perl-based rename command (sometimes called prename) is powerful for pattern substitution:

rename -n 's/ACDC/AC-DC/g' *.xxx

Note: The -n flag performs a dry run. Remove it to actually rename files.

Using find with exec

For recursive operations through subdirectories:

find . -name "ACDC*.xxx" -exec rename 's/ACDC/AC-DC/' {} +

For filenames containing spaces, apostrophes, or other special characters:

find . -name "*ACDC*" -print0 | while IFS= read -r -d '' file; do
    newname="${file//ACDC/AC-DC}"
    mv "$file" "$newname"
done

Save this as replace_in_filename.sh:

#!/bin/bash
if [ $# -ne 2 ]; then
    echo "Usage: $0 old_pattern new_pattern"
    exit 1
fi

for file in *"$1"*; do
    if [ -f "$file" ]; then
        newname="${file//$1/$2}"
        mv -i "$file" "$newname"
    fi
done

Usage: ./replace_in_filename.sh ACDC AC-DC

Always verify changes before executing:

for file in ACDC*.xxx; do
    echo "Would rename: $file → ${file/ACDC/AC-DC}"
done

For macOS users, install the Perl rename command via Homebrew:

brew install rename

#!/bin/bash
# This script demonstrates how to rename multiple files by replacing text patterns
# Example: Changing "ACDC" to "AC-DC" in all matching filenames


When managing media collections or project files, we often need to standardize naming conventions. A common scenario involves replacing specific patterns in multiple filenames while preserving the rest of the name structure.


For simple replacements in the current directory:


for file in ACDC*; do
    mv "$file" "${file/ACDC/AC-DC}"
done



For complex patterns or recursive operations:


find . -name "ACDC*" -type f | while read -r file; do
    newname=$(echo "$file" | sed 's/ACDC/AC-DC/g')
    mv "$file" "$newname"
done



When you need conditional replacements or pattern matching:


find . -type f -name "*ACDC*" | awk -v old="ACDC" -v new="AC-DC" '{
    oldname=$0
    gsub(old, new)
    system("mv \"" oldname "\" \"" $0 "\"")
}'



Always test with echo first:


for file in ACDC*; do
    echo mv "$file" "${file/ACDC/AC-DC}"
done



For filenames containing spaces or special characters:


find . -name "*ACDC*" -print0 | while IFS= read -r -d '' file; do
    dir=$(dirname "$file")
    base=$(basename "$file")
    newbase=$(echo "$base" | sed 's/ACDC/AC-DC/g')
    mv "$file" "$dir/$newbase"
done



For maximum compatibility across Unix-like systems:


perl -e 'for (@ARGV) { $new = $_; $new =~ s/ACDC/AC-DC/g; rename($_, $new) unless $_ eq $new }' ACDC*