How to batch rename files in a directory from a list of names in a text file
Categories:
Batch Rename Files from a List: A Comprehensive Guide
Learn how to efficiently rename multiple files in a directory using a list of new names provided in a text file, covering both Linux/macOS (Bash) and Windows (PowerShell).
Renaming a large number of files manually can be a tedious and error-prone task. Whether you're organizing photos, standardizing document names, or processing data, automating the renaming process is a significant time-saver. This article will guide you through batch renaming files in a directory using a list of new names from a text file, providing solutions for both Linux/macOS (Bash) and Windows (PowerShell) environments.
Understanding the Core Concept
The fundamental idea behind this process is to establish a one-to-one mapping between existing files in a directory and a list of desired new names. This mapping is typically achieved by reading both the current filenames and the new names in a specific order (e.g., alphabetical, creation date, or a custom order). The new names are usually provided in a simple text file, with one new name per line. The script then iterates through these lists, applying the new name to the corresponding old file.
flowchart TD A[Start] --> B{Prepare Old Files List} B --> C[Prepare New Names List (Text File)] C --> D{Read Old File and New Name Pair} D -- For each pair --> E[Rename Old File to New Name] E --> D D -- No more pairs --> F[End]
Workflow for batch renaming files from a list.
Prerequisites and Setup
Before you begin, ensure you have the following:
A directory with files to be renamed: For example,
file1.txt
,file2.txt
,image.jpg
.A text file containing the new names: Each new name should be on a separate line, in the exact order you want them applied to the old files. For instance, if your old files are sorted alphabetically and you want to rename them in that order, your new names list should also be in that corresponding order.
Example
new_names.txt
:document_a.txt document_b.txt photo_c.jpg
Backup your files: Always create a backup of your original files before performing any batch operations. This prevents accidental data loss if something goes wrong.
Batch Renaming in Linux/macOS (Bash)
In a Unix-like environment, you can use a combination of ls
, read
, and mv
commands within a Bash script. The key is to ensure that the order of files read from the directory matches the order of names in your new_names.txt
file. A common approach is to sort both lists alphabetically.
#!/bin/bash
# Directory containing the files to rename
TARGET_DIR="./my_files"
# Text file with new names, one per line
NEW_NAMES_FILE="./new_names.txt"
# Check if the directory exists
if [ ! -d "$TARGET_DIR" ]; then
echo "Error: Directory '$TARGET_DIR' not found."
exit 1
fi
# Check if the new names file exists
if [ ! -f "$NEW_NAMES_FILE" ]; then
echo "Error: New names file '$NEW_NAMES_FILE' not found."
exit 1
fi
# Get a sorted list of current files (adjust pattern if needed, e.g., *.txt)
OLD_FILES=($(ls -1v "$TARGET_DIR"/*))
# Read new names into an array
mapfile -t NEW_NAMES < "$NEW_NAMES_FILE"
# Check if the number of old files matches the number of new names
if [ ${#OLD_FILES[@]} -ne ${#NEW_NAMES[@]} ]; then
echo "Error: Number of old files (${#OLD_FILES[@]}) does not match number of new names (${#NEW_NAMES[@]})."
exit 1
fi
# Loop through and rename files
for i in "${!OLD_FILES[@]}"; do
OLD_PATH="${OLD_FILES[$i]}"
NEW_NAME="${NEW_NAMES[$i]}"
NEW_PATH="$TARGET_DIR/$NEW_NAME"
echo "Renaming \"$OLD_PATH\" to \"$NEW_PATH\""
mv "$OLD_PATH" "$NEW_PATH"
done
echo "Batch renaming complete."
Bash script for batch renaming files.
ls -1v
command sorts files numerically and alphabetically, which is often what you want. If your files have a different naming convention (e.g., file_001.txt
, file_002.txt
), this sorting helps maintain the correct order. Adjust the TARGET_DIR
and NEW_NAMES_FILE
variables to match your setup.Batch Renaming in Windows (PowerShell)
PowerShell offers powerful cmdlets for file system manipulation. We'll use Get-ChildItem
to list files, Get-Content
to read the new names, and Rename-Item
to perform the renaming. Similar to Bash, ensuring the order of files and new names is crucial.
# Directory containing the files to rename
$targetDir = ".\my_files"
# Text file with new names, one per line
$newNamesFile = ".\new_names.txt"
# Check if the directory exists
if (-not (Test-Path $targetDir -PathType Container)) {
Write-Error "Error: Directory '$targetDir' not found."
exit
}
# Check if the new names file exists
if (-not (Test-Path $newNamesFile -PathType Leaf)) {
Write-Error "Error: New names file '$newNamesFile' not found."
exit
}
# Get a sorted list of current files (adjust filter if needed, e.g., *.txt)
$oldFiles = Get-ChildItem -Path $targetDir | Sort-Object Name
# Read new names into an array
$newNames = Get-Content -Path $newNamesFile
# Check if the number of old files matches the number of new names
if ($oldFiles.Count -ne $newNames.Count) {
Write-Error "Error: Number of old files ($($oldFiles.Count)) does not match number of new names ($($newNames.Count))."
exit
}
# Loop through and rename files
for ($i = 0; $i -lt $oldFiles.Count; $i++) {
$oldFile = $oldFiles[$i]
$newName = $newNames[$i]
$newPath = Join-Path -Path $targetDir -ChildPath $newName
Write-Host "Renaming '$($oldFile.FullName)' to '$newPath'"
Rename-Item -Path $oldFile.FullName -NewName $newName -Force
}
Write-Host "Batch renaming complete."
PowerShell script for batch renaming files.
Sort-Object Name
cmdlet sorts files alphabetically by their name. If you need a different sorting order (e.g., by creation time), you can change Sort-Object Name
to Sort-Object CreationTime
.Advanced Considerations and Best Practices
While the provided scripts cover the basic scenario, real-world situations can be more complex. Consider these points:
- File Extensions: The scripts assume the new names in
new_names.txt
include the desired file extension. If you only provide base names, you'll need to extract the original extension and append it. - Error Handling: The scripts include basic checks for directory and file existence, and matching counts. You might want to add more robust error handling, such as checking for duplicate new names or invalid characters.
- Simulating Renames (Dry Run): Before executing the
mv
orRename-Item
commands, it's a good practice to perform a "dry run" where you only print what would be renamed without actually doing it. This helps verify your logic. - Handling Subdirectories: The current scripts only process files directly within the
TARGET_DIR
. To include subdirectories, you would need to modify thels
orGet-ChildItem
commands (e.g.,Get-ChildItem -Recurse
). However, this complicates the mapping with a flatnew_names.txt
file. - Non-matching Counts: If the number of old files doesn't match the number of new names, the scripts will exit with an error. You might want to implement logic to handle this, such as skipping extra new names or leaving unmatched old files as they are.
Bash Dry Run
#!/bin/bash
... (same setup as before) ...
Loop through and print what would be renamed (DRY RUN)
for i in "${!OLD_FILES[@]}"; do OLD_PATH="${OLD_FILES[$i]}" NEW_NAME="${NEW_NAMES[$i]}" NEW_PATH="$TARGET_DIR/$NEW_NAME"
echo "DRY RUN: Would rename \"$OLD_PATH\" to \"$NEW_PATH\""
# mv "$OLD_PATH" "$NEW_PATH" # Commented out for dry run
done
echo "Dry run complete. No files were actually renamed."
PowerShell Dry Run
... (same setup as before) ...
Loop through and print what would be renamed (DRY RUN)
for ($i = 0; $i -lt $oldFiles.Count; $i++) { $oldFile = $oldFiles[$i] $newName = $newNames[$i] $newPath = Join-Path -Path $targetDir -ChildPath $newName
Write-Host "DRY RUN: Would rename '$($oldFile.FullName)' to '$newPath'"
# Rename-Item -Path $oldFile.FullName -NewName $newName -Force # Commented out for dry run
}
Write-Host "Dry run complete. No files were actually renamed."