Adding text to the beginning and end of a number of files?

2

I have a number of files in a directory hierarchy. For each file, I'd like to add "abcdef" to the beginning, on its own line, and "ghijkl" to the end, on its own line. For example, if the files initially contained:

# one/foo.txt
apples
bananas

# two/three/bar.txt
coconuts

Then afterwards, I'd expect them to contain:

# one/foo.txt
abcdef
apples
bananas
ghijkl

# two/three/bar.txt
abcdef
coconuts
ghijkl

What's the best way to do this?

I've gotten as far as:

# put stuff at start of file
find . -type f -print0 | xargs -0 sed -i 's/.../abcdef/g'

# put stuff at end of file
find . -type f -print0 | xargs -0 sed -i 's/.../ghijkl/g'

but I can't seem to figure out how what to put in the ellipses.

John Feminella

Posted 2012-08-30T14:53:46.883

Reputation: 1 582

I can’t help but notice how simple and straightforward this is in Windows: for %i in (*) do echo abcdef>t.tmp & type "%i">>t.tmp & echo ghijkl>>t.tmp & move /y t.tmp "%i" or alternately, echo abcdef>header.tmp & echo ghijkl>footer.tmp & for %i in (*) do copy /y headert.tmp+"%i"+footer.tmp "%i" & del header.tmp & del footer.tmp – Synetech – 2012-08-30T15:27:23.313

@Synetech: Does that work recursively? – Dennis – 2012-08-30T15:37:01.780

1@Dennis, as in for files in subfolders? No, but you can add a /r to the for loop to make it recursive. – Synetech – 2012-08-30T16:41:11.817

Answers

3

This isn't a job for sed. To add lines, just use I/O redirection.

For a single file named filename, you can do the following:

mv filename temp
(echo abcdef ; cat temp ; echo ghijkl) > filename
rm temp

To do this automatically to all files in the current directory, use find and xargs:

find -type f -print0 | xargs -0 -I % sh -c '
    mv "%" temp
    (echo abcdef ; cat temp ; echo ghijkl) > "%"
'
rm temp

Dennis

Posted 2012-08-30T14:53:46.883

Reputation: 42 934

I would suggest a tweak: (echo abcdef; cat filename; echo ghijkl) > temp;  cp temp filename;  rm temp, to retain attributes (owner and mode) on the files. – Scott – 2012-08-30T16:28:08.710

Ownership and permissions might get lost by simply moving the file. Good point, @Scott. But copying instead of moving might come with a great performance penalty (if the files are big), so I'd use chmod and chown with the --reference switch in this case. – Dennis – 2012-08-30T16:34:55.160

2

If you have GNU sed available you can use the i\ and a\ constructs:

Use line addresses to apply to first and last line respectively:

find . -type f -print0 | xargs -0 sed -i -e '1i\abcdef' -e '$a\ghijkl'

Thor

Posted 2012-08-30T14:53:46.883

Reputation: 5 178

To me this seems a more elegant, less error prone and more efficient solution than the one accepted. – potong – 2012-09-03T23:30:24.150

-1

For files in directory as file
echo "abcde" && cat file && echo "fghijk" > file

patrick_corrigan

Posted 2012-08-30T14:53:46.883

Reputation: 107

1This will not work for two reasons: 1. cat is not echo. It won't print abcdef but display an error. 2. Input file and output file cannot be the same. – Dennis – 2012-08-30T15:18:35.400

This won't work either. It writes fghijk to file and deletes all the rest! It wouldn't work with parentheses either, since cat's input and output file can't be identical. – Dennis – 2012-08-30T15:33:31.960

1Please do not just guess as to the solution for a problem. If you don't know the solution, take a moment to research (trying this yourself isn't too time-consuming in this case) or refrain from posting guesses. – Daniel Beck – 2012-08-30T15:36:24.907

Sorry I just got overly excited:P I'll try to control myself in future :D – patrick_corrigan – 2012-08-31T13:04:31.047