Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I would like to modify a bunch of text files from the terminal, more precisey:

add the string '50' to the first line of every text file in /mydat/ ?

Alternatively, if you know of a link to a page on the web that lists commands to manipulate text files from the shell...

share|improve this question
    
Questions are always welcome here, but you might find this useful: commandlinefu.com lists a bunch of commands and tricks for use in the shell, and it has lots of stuff about text-file manipulation. –  Firefeather Nov 3 '10 at 19:08
    
@Firefeather:> thanks. I was looking for something like this! I think you can add this as a legit response. –  user2413 Nov 7 '10 at 12:48
    
You're welcome. I'll add it as a response, then. :) –  Firefeather Nov 7 '10 at 23:43
add comment

5 Answers 5

up vote 7 down vote accepted

find and sed are your weapons of choice:

find /mydat/ -exec sed '1i 50' {} \;

That will stick 50 followed by a new line on the beginning of the file.

Alternatively if you don't need recursion or complex selectors for find you can drop find completely:

sed '1i 50' *
share|improve this answer
    
> thanks. However a little problem remains (see appended questions for an example). –  user2413 Nov 2 '10 at 19:09
    
Fixed. I've also added a simplified version that should still do what you need. find is more powerful but you might not need it. I'll add that both versions are somewhat more simple than all these convoluted bash loops. –  Oli Nov 2 '10 at 19:22
    
One last thing. I have a file timing.txt and i need to replace the first line of that file by the constant string "49". How do you modify your command? –  user2413 Nov 2 '10 at 20:07
    
ok found: sed '1d' timing0.txt > timing0.txt –  user2413 Nov 2 '10 at 20:29
add comment

To edit a file, you need an editor. ed and ex are examples of command based editors, which is useful for editing files from a script. Here's an example inserting a line to every file with .txt extension in /mydata, using ed:

#!/bin/bash
for file in /mydata/*.txt; do
    printf '%s\n' 0a 50 . w | ed -s "$file"
done

That'll handle all kinds of odd characters in the filenames too, unlike all the examples using for-loops with ls in the answers given so far.

Here's a link describing how to use ed: http://bash-hackers.org/wiki/doku.php?id=howto:edit-ed

For getting to grips with bash, I strongly recommend reading http://mywiki.wooledge.org/BashGuide

share|improve this answer
    
"getting to grips with bash".. I'm starting to see that your "mysterious" answers can contain pearls of bash wisdom... It does a very simple "interactive" real-time edit of each matching file. I've had problems with, and heard other moanings, about sed's -i (inline write).. your method avoids it (and/or the need for a secondary file, which sed does anyhow) ...I read your link about ed, and how it is interactive vs. sed's stream nature.. From reading your link and ed's info/man page, I'm getting a better sense of what is actually going on inside sed, and about bash/shell in general :) –  Peter.O Jan 21 '11 at 2:20
    
add comment

Essentially you need to loop through every text file in a directory, then add a small string to the start. It's not hard when you break it down into two steps.

To add the string to the beginning of a file, the format would be this:

echo "50 $( cat file.txt )" > file.txt

If you get a cannot overwrite existing file error, you need to disable noclobber

set +o noclobber

Now you just need to drop that in a loop that loops through the files you want to alter.

for FILE in $( ls /mydata/ | grep txt$ ) ; do
  echo "${FILE}"
done

If that outputs all the files you want to alter correctly, add in the command to alter the files (as below). If not, alter the grep statement until it matches what you need.

for FILE in $( ls /mydata/ | grep txt$ ) ; do
  echo "50 $( cat ${FILE} )" > "${FILE}"
done

And if you want it done in one line:

for FILE in $( ls /mydata/ | grep txt$ ) ; do echo "50 $( cat ${FILE} )" > "${FILE}"; done

Edit

If you want the 50 on its own line, use printf along with \n instead of echo, as below.

for FILE in $( ls /mydata/ | grep txt$ ) ; do printf "50\n$( cat ${FILE} )" > "${FILE}"; done
share|improve this answer
    
> thanks. However this gives me an error (bash: syntax error near unexpected token `FILE'). –  user2413 Nov 2 '10 at 19:07
    
Ah sorry, I accidentally put brackets in used in bash comparisons, the updated answer should work. –  tj111 Nov 2 '10 at 19:15
    
> your first command works great (changing file.txt by the real adress...except it add 50 to the first line (i want 50 to be the first line...i.e. 50+new line then rest of file (but i couldn't combine your solution with that of Oli). –  user2413 Nov 2 '10 at 19:16
    
Works superbly. Thanks a lot. –  user2413 Nov 2 '10 at 19:20
    
add comment

Since you asked, commandlinefu.com lists a bunch of commands and tricks for use in the shell, and it has lots of stuff about text-file manipulation.

share|improve this answer
    
+1. Thanks: this is very helpful ! –  user2413 Nov 8 '10 at 12:48
    
+1 for the Link. It is very helpful –  Anwar Shah Sep 24 '12 at 15:41
add comment

It's relatively straightforward to add text to the end of files. For BASH: echo 50 >> file.txt will append 50 to the end of of file.txt. Wrap that up in a for loop like so: for $FILE in 'ls' do echo 50 >> $FILE; done;for $FILE in * do echo 50 >> $FILE; done; will iterate over all the files in the current directory appending 50 to the end. Note that the single quotes are actually `, but that's the indicator for code markup here... blech. To add it to the top of each file, create a temporary file and echo 50 into it, then echo the contents of the file after that. Then rename the file to overwrite the original. Wrap it up in a script and you're set!

#!/bin/bash

echo "Adding 50 to each file in current directory."

for $FILE in *
do
[[ -f "$i" ]] || continue
echo "50" >> tmp
cat "$FILE" >> tmp
mv tmp "$FILE"
done

That should work, but run it on a test directory before anything important.

Edit: Updated the script as suggested in Mahesh's comment.

share|improve this answer
    
In response to Oli's post, sed is a very powerful language for doing things like this; but be careful when using find's -exec option. I've fragged 30 GB of data by mistyping an -exec command before. –  Nick Pascucci Nov 2 '10 at 18:56
    
thanks. But '50' has to be appended at the begining of the text file. –  user2413 Nov 2 '10 at 19:08
    
The script at the end should do that just fine, by first appending 50 to a temporary file, then appending the remainder of the file and moving the temporary file to overwrite the old one. –  Nick Pascucci Nov 2 '10 at 19:18
    
> just saw your comment. Actually i really like the logic of it, but Oli's answer launched me unto learning sed a bit which was really helpful these last 24 hours. –  user2413 Nov 3 '10 at 19:08
    
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.