Append a text to the end of multiple files in Linux

I need to append the following code to the end to all the php files in a directory and its sub directory:

</div>
<div id="preloader" style="display:none;position: absolute;top: 90px;margin-left: 265px;">
<img src="ajax-loader.gif"/>
</div>

I have tried with

echo "my text" >> *.php

But terminal showed the error:

bash : *.php: ambiguous redirect

What should I do. there are hundreds of files to add this code segment and it would be a real tough time adding it in each file. Thanks in advance.


I usually use tee because I think it looks a little cleaner and it generally fits on one line.

echo "my text" | tee -a *.php

You don't specify the shell, you could try the foreach command. Under tcsh (and I'm sure a very similar version is available for bash) you can say something like interactively:

foreach i (*.php)
foreach> echo "my text" >> $i
foreach> end

$i will take on the name of each file each time through the loop.

As always, when doing operations on a large number of files, it's probably a good idea to test them in a small directory with sample files to make sure it works as expected.

Oops .. bash in error message (I'll tag your question with it). The equivalent loop would be

for i in *.php
do 
   echo "my text" >> $i
done

If you want to cover multiple directories below the one where you are you can specify

*/*.php

rather than *.php


BashFAQ/056 does a decent job of explaining why what you tried doesn't work. Have a look.

Since you're using bash (according to your error), the for command is your friend.

for filename in *.php; do
  echo "text" >> "$filename"
done

If you'd like to pull "text" from a file, you could instead do this:

for filename in *.php; do
  cat /path/to/sourcefile >> "$filename"
done

Now ... you might have files in subdirectories. If so, you could use the find command to find and process them:

find . -name "*.php" -type f -exec sh -c "cat /path/to/sourcefile >> {}" \;

The find command identifies what files using conditions like -name and -type, then the -exec command runs basically the same thing I showed you in the previous "for" loop. The final \; indicates to find that this is the end of arguments to the -exec option.

You can man find for lots more details about this.

The find command is portable and is generally recommended for this kind of activity especially if you want your solution to be portable to other systems. But since you're currently using bash, you may also be able to handle subdirectories using bash's globstar option:

shopt -s globstar
for filename in **/*.php; do
  cat /path/to/sourcefile >> "$filename"
done

You can man bash and search for "globstar" for more details about this. This option requires bash version 4 or higher.

NOTE: You may have other problems with what you're doing. PHP scripts don't need to end with a ?>, so you might be adding HTML that the script will try to interpret as PHP code.


You can use sed combined with find. Assume your project tree is

    /MyProject/ 
    /MyProject/Page1/file.php
    /MyProject/Page2/file.php
    etc.        
  1. Save the code you want to append on /MyProject/. Call it append.txt
  2. From /MyProject/ run:

    find . -name "*.php" -print | xargs sed -i '$r append.txt'
    

    Explain:

    • find does as it is, it looks for all .php, including subdirectories
    • xargs will pass (i.e. run) sed for all .php that have just been found
    • sed will do the appending. '$r append.txt' means go to the end of the file ($) and write (paste) whatever is in append.txt there. Don't forget -i otherwise it will just print out the appended file and not save it.

Source: http://www.grymoire.com/unix/Sed.html#uh-37


You can do (Work even if there's space in your file path) :

#!/bin/bash

# Create a tempory file named /tmp/end_of_my_php.txt
cat << EOF > /tmp/end_of_my_php.txt
</div>
<div id="preloader" style="display:none;position: absolute;top: 90px;margin-left: 265px;">
<img src="ajax-loader.gif"/>
</div>
EOF

find . -type f -name "*.php" | while read the_file
do
    echo "Processing $the_file"
    #cp "$the_file" "${the_file}.bak" # Uncomment if you want to save a backup of your file
    cat /tmp/end_of_my_php.txt >> "$the_file"
done

echo
echo done

PS: You must run the script from the directory you want to browse