To append text to multiple files in a Bash script, you use a loop that applies the >> redirection operator to each file in turn. The basic pattern is for file in file1 file2 file3; do echo "text" >> "$file"; done, which adds the same line to every file without overwriting existing content.
How Appending Works in Bash
In Bash, the >> operator redirects output and appends it to the end of a file. If the file does not exist, it is created. Unlike >, which truncates the file to zero bytes before writing, >> preserves all existing content and adds new data after the last byte. This is the core mechanism for appending text to a single file, and it is the same mechanism used when you target multiple files inside a loop.
Because >> is a shell operator, it works with any command that produces standard output: echo, printf, cat, sed, or even the output of another script. For example, date >> log.txt appends the current date and time to log.txt.
Appending the Same Text to Multiple Files
When you need to add the same line to several files, a for loop is the simplest and most readable approach. Here is a basic script:
#!/bin/bash
for file in file1.txt file2.txt file3.txt; do
echo "This line is added." >> "$file"
done
This appends the exact string This line is added. to each of the three files. If you want to include a newline at the end, echo does that automatically. To append multiple lines, use printf with \n in the format string:
printf "First line\nSecond line\n" >> "$file"
You can also use a here-document to append a longer block of text:
cat >> "$file" <<EOF
Line one
Line two
EOF
Appending Different Text to Each File
Sometimes you need to append different content to each file. In that case, you can use an array of filenames and a corresponding array of text, or simply process each file individually in the loop body. For example:
#!/bin/bash
files=("a.txt" "b.txt" "c.txt")
texts=("Content for A" "Content for B" "Content for C")
for i in "${!files[@]}"; do
echo "${texts[$i]}" >> "${files[$i]}"
done
This uses the array index to pair each file with its text. Alternatively, you can use a case statement inside the loop to choose the text based on the filename, which is more readable when the mapping is simple.
Using find to Append to Many Files
When you need to append to every file in a directory tree that matches a pattern, combine find with a loop. The -exec option can run a command on each file, but for appending text you need to call a shell because redirection is a shell feature. The safest way is:
find /path/to/dir -type f -name "*.log" -exec sh -c 'echo "log entry" >> "$1"' _ {} \;
This runs sh -c for each found file, with {} passed as the first argument. The underscore is a placeholder for the script name in $0. Alternatively, you can pipe the results to a while read loop:
find /path/to/dir -type f -name "*.log" | while read -r file; do
echo "log entry" >> "$file"
done
This approach handles filenames with spaces correctly as long as read -r is used and the IFS is left at its default (which splits on newlines only).
Common Pitfalls and How to Avoid Them
One frequent mistake is forgetting to quote the filename variable. If a filename contains spaces or special characters, an unquoted $file will be split into multiple words, causing the command to fail or append to the wrong file. Always use "$file".
Another issue is using > instead of >>, which truncates the file and destroys existing content. Double-check your redirection operator before running the script, especially if you are modifying important files.
If you are appending to files that do not exist yet, >> will create them. However, if the parent directory does not exist, the command fails with a “No such file or directory” error. You can create the directory with mkdir -p beforehand.
When using find with -exec, be careful with special characters in the text you are appending. If the text contains $, backticks, or backslashes, they may be interpreted by the shell. Use single quotes around the sh -c command and escape any single quotes in the text.
Comparing Methods: Loop vs. find vs. tee
The for loop is the most straightforward and is ideal when you have a known list of files. It is also the fastest for a small number of files. The find approach is better for large directory trees or when you do not know the filenames in advance.
Another tool is tee, which reads from standard input and writes to both standard output and files. To append to multiple files with tee, you can use:
echo "text" | tee -a file1.txt file2.txt file3.txt
The -a flag makes tee append instead of overwrite. This is concise and works well when you have a fixed list of files, but it also prints the text to standard output, which may be undesirable in a script. You can suppress that by redirecting standard output to /dev/null:
echo "text" | tee -a file1.txt file2.txt > /dev/null
For very large numbers of files, a loop is generally more efficient than spawning multiple tee processes, but the difference is negligible unless you are dealing with thousands of files.
Safety and Backup Considerations
Appending is generally safe because it does not overwrite existing data, but it is still possible to make mistakes. Before running a script that modifies many files, it is wise to test it on a copy or use echo to print the commands instead of executing them. For example, you can replace >> with a comment to see which files would be affected.
If you are appending to system files or configuration files, consider making a backup first. A simple cp file file.bak before the loop can save you from a costly mistake. Also, be aware that appending to a file that is being written by another process can cause interleaved data, so avoid running such scripts on live log files unless you understand the concurrency implications.
Finally, always test your script with a small sample of files first. Use bash -n script.sh to check for syntax errors, and run it with set -u (error on undefined variables) and set -e (exit on error) to catch problems early.
Frequently Asked Questions
How do I append a blank line to multiple files?
Simply use echo with no arguments: echo >> "$file". This appends a single newline character, effectively adding a blank line at the end of the file.
Can I append the content of one file to many other files?
Yes, use cat source.txt >> "$file" inside the loop. This reads the contents of source.txt and appends them to each target file.
What if the file names contain spaces?
Always quote the variable: "$file". In a for loop, if you are iterating over a list of filenames with spaces, you need to use a while read loop with a here-string or a file list, because the default for loop splits on whitespace.
How do I append text to every file in the current directory?
Use for file in *; do if [ -f "$file" ]; then echo "text" >> "$file"; fi; done. The -f check ensures you only append to regular files, not directories.
Is there a way to append without creating the file if it doesn’t exist?
No, >> always creates the file if it does not exist. If you want to avoid creating new files, you can check for existence first with [ -f "$file" ] and only then append.
Can I use a variable for the text to append?
Yes, just put the variable inside double quotes: echo "$text" >> "$file". This preserves spaces and special characters in the variable.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Secure Boot Battlefield 6 ASUS: Fix & Enable Guide
- Best Tech Websites to Follow for Pros & Beginners
- Second Wind Quest Walkthrough: Where Winds Meet6.00 min/km
- Enshrouded Weapon Upgrade Guide: How to Improve Gear5.00 min/km
- Connect Phone to Controller for Cloud Gaming
- Python Search Highlighting: Snippets & Matches