how to copy and rename file with for loop in bash script?
Categories:
Copy and Rename Files with a Bash for
Loop
Learn how to efficiently copy and rename multiple files using a for
loop in Bash scripts, covering various renaming strategies and best practices.
Automating file operations is a common task in shell scripting. When you need to copy a set of files and apply a new naming convention to each copied file, a for
loop in Bash is an incredibly powerful and flexible tool. This article will guide you through the process, demonstrating how to construct effective loops for various renaming scenarios, from simple prefixes to more complex pattern-based transformations.
Basic File Copy and Rename with a for
Loop
The fundamental approach involves iterating over a list of source files, and for each file, constructing a new destination filename before executing the cp
command. This method is versatile and can be adapted to many different renaming patterns. We'll start with a simple example: adding a prefix to copied files.
#!/bin/bash
SOURCE_DIR="./original_files"
DEST_DIR="./renamed_copies"
PREFIX="new_"
mkdir -p "$DEST_DIR"
for file in "$SOURCE_DIR"/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
cp "$file" "$DEST_DIR/${PREFIX}${filename}"
echo "Copied '$file' to '$DEST_DIR/${PREFIX}${filename}'"
fi
done
Basic for
loop to copy files and add a prefix to their names.
"$file"
, "$DEST_DIR"
) to prevent word splitting and glob expansion issues. This ensures your script handles filenames correctly.Advanced Renaming Strategies
Beyond simple prefixes, Bash offers powerful string manipulation capabilities that can be used within a for
loop to achieve more complex renaming. This includes replacing parts of a filename, adding suffixes, or even using regular expressions for pattern matching and substitution. Let's explore some common scenarios.
flowchart TD A[Start Loop: Iterate over files] --> B{Is it a regular file?} B -- Yes --> C[Extract original filename] C --> D[Construct new filename (e.g., add prefix, replace string)] D --> E[Execute `cp` command: original_file -> new_file] E --> F[Log action] F --> G{More files?} G -- Yes --> A G -- No --> H[End]
Flowchart illustrating the process of copying and renaming files within a for
loop.
Renaming by Replacing Substrings
A common requirement is to replace a specific string within the filename. Bash parameter expansion allows for powerful substring replacement directly within the loop. This is particularly useful for versioning, changing file types, or standardizing names.
#!/bin/bash
SOURCE_DIR="./reports"
DEST_DIR="./archive_reports"
OLD_STRING="_draft"
NEW_STRING="_final"
mkdir -p "$DEST_DIR"
for file in "$SOURCE_DIR"/*"$OLD_STRING"*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
new_filename="${filename//$OLD_STRING/$NEW_STRING}"
cp "$file" "$DEST_DIR/${new_filename}"
echo "Copied '$file' to '$DEST_DIR/${new_filename}'"
fi
done
Copying files and replacing a substring in their names.
Adding a Timestamp or Sequence Number
For backup or versioning purposes, you might want to add a timestamp or a sequential number to the copied files. This can be achieved by incorporating the date
command or a counter variable into your loop.
#!/bin/bash
SOURCE_DIR="./logs"
DEST_DIR="./daily_backups"
mkdir -p "$DEST_DIR"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
for file in "$SOURCE_DIR"/*.log; do
if [ -f "$file" ]; then
filename=$(basename "$file")
# Remove .log extension, add timestamp, then re-add .log
base_name="${filename%.log}"
cp "$file" "$DEST_DIR/${base_name}_${TIMESTAMP}.log"
echo "Copied '$file' to '$DEST_DIR/${base_name}_${TIMESTAMP}.log'"
fi
done
Copying log files and appending a timestamp to their names.
1. Define Source and Destination
Clearly define SOURCE_DIR
and DEST_DIR
variables at the beginning of your script. This makes the script easier to read and modify.
2. Create Destination Directory
Use mkdir -p "$DEST_DIR"
to ensure the destination directory exists. The -p
flag prevents errors if the directory already exists.
3. Iterate Safely
Use for file in "$SOURCE_DIR"/*; do
to iterate over files. Always check if [ -f "$file" ]
to ensure you are processing regular files and not directories or other special file types.
4. Extract Filename
Use filename=$(basename "$file")
to get just the filename without the path. This is crucial for constructing the new name correctly.
5. Construct New Filename
Apply Bash parameter expansion (e.g., ${filename//OLD/NEW}
, ${filename%.ext}
, ${filename%/*}
) to manipulate the filename as needed. Be precise with your patterns.
6. Execute Copy Command
Use cp "$file" "$DEST_DIR/${new_filename}"
to perform the copy operation. Double-check the source and destination paths.
7. Add Logging
Include echo
statements to provide feedback on which files are being processed and what their new names are. This is invaluable for debugging and monitoring.