18

I want to remove the first line of multiple text files and replace it with another line. Is there a way to do this using the terminal?

I know how to use vim, is there a way to automate it with it? I want to avoid doing it manually (as in editing each file individually).

If possible I'd like to avoid installing new libraries (especially for something like that which i consider very simple - but I could be wrong).

Thanks in advance!

21

You can use sed :

sed -i.bak '1s/^.*$/new line/' *.txt

This will replace the first line of all .txt files in the current directory with the text new line, change it to meet your need.

Also the original files will be backed up with .bak extension, if you don't want that just use :

sed -i '1s/^.*$/new line/' *.txt
  • Thank you! sed is actually what i was looking for! – TomTsagk Aug 1 '15 at 23:08
  • @TomTsagk Glad i could help :) – heemayl Aug 1 '15 at 23:08
11

Well, using vim itself:

vim -Nesc 'bufdo call setline(1,"This is the replacement.") | wq' file1 file2 ...

What this does:

  • setline (n, text), well, is a function that sets line n to text.
  • call is needed to call functions.
  • bufdo is used to repeat a command across buffers (without a range, it acts on all buffers).
  • wq saves and quits the buffer. We need to do this before moving on to the next buffer, so this command is chained to the call command using |.
  • -c cmd runs cmd is a command-mode command after loading the first buffer.
  • Nes turns on no-compatible, silent, ex-mode, which is better for non-interactive processing.

Benefits:

  • The setline text content can be anything - an & in a sed replacement text can have unintended effects.
  • sed seems much easier to use, but it's really awesome that vim can do the same! Thanks a lot for your answer! – TomTsagk Aug 1 '15 at 23:23
  • @TomTsagk well, I just wanted to illustrate how you could act across multiple files (bufdo). Consider you having the files already open and ... And to show an alternate to 1s/foo/bar/. – muru Aug 2 '15 at 0:33
  • Awesoming!!! <3_<3 – Campa Aug 5 '15 at 6:50
3

A few other options:

  • awk (needs a relatively new version of GNU awk)

    $ awk -i inplace -vline="new line" '(FNR==1){print line; next}1;' *.txt
    
  • Perl/shell

    $ for f in *txt; do
        perl -i -lne '$.==1 ? print "new line" : print' "$f"
      done
    
  • Shell/coreutils

    $ for f in *txt; do 
        ( echo "new line"; tail -n+2 "$f" ) > foo && mv foo "$f"; 
      done
    
2

This script will do as you requested, placing the changed files in a new directory without actually changing the originals.

d=/tmp/cooked
mkdir $d
for f in *  #will match all files in current directory; adjust as desired
do
  echo "This is the new 1st line" > /${d}/${f}
  sed 1d ${f} >> /${d}/${f}
done
  • I was slow answering (tested my code)...and I like heemayl's solution a lot better! – Charles Boling Aug 1 '15 at 23:07
0

Using gawk

gawk -i inplace 'FNR==1 {$_="your_replacement"}; {print}' *.txt

Example

% cat foo.txt 
1
2
3
4

% cat bar.txt 
1
2
3
4

% gawk -i inplace 'FNR==1 {$_="your_replacement"}; {print}' *.txt

% cat foo.txt                                                    
your_replacement
2
3
4

% cat bar.txt                                                    
your_replacement
2
3
4
0

jEdit: I use it for mass-find-and-replace. It's powerful with the ability to use RegEx - Regular Expressions. You can operate on files within a directory, specify file extensions, e.g., ".html" and so forth. And, you can look at the locale of the candidate change in context, in a GUI. jEdit is great.

jEdit is available via Ubuntu's software center.

0

The tail and cat commands would do this easily:

tail -n +1 $file > tmpfile
cat newfirstline tmpfile >$file

Wrap those in a suitable loop and perhaps use a proper and righteous temporary file instead of a hard-coded temporary file name. I believe bash and other shells have a syntax for creating temporary files.

The -n option of tail has two interpretations depending on whether the argument has a plus sign. If it has a plus sign then it means to show the tail of the file starting at the given line number. Otherwise the number is the number of lines, including the last line, that tail is supposed to output.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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