Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I want to replace the 5th line of multiple text files (file1.txt,file2.txt,file3.txt,file4.txt) with the string " Good Morning " using a single terminal command.

All the text files are located on my ~/Desktop.

Note: My desktop consists of 6 .txt files.I want to apply the change to above mentioned 4 text files only.

share|improve this question
up vote 22 down vote accepted

Here are a few approaches. I am using brace expansion (file{1..4}.txt) which means file1.txt file2.txt file3.txt file4.txt

  1. Perl

    perl -i -pe 's/.*/ Good Morning / if $.==5' file{1..4}.txt
    

    Explanation:
    -i : causes perl to edit the files in place, changing the original file.
    -p : means read the input file line by line, apply the script and print it
    -e : allows you to pass a script from the command line
    s/.*/ Good Morning / : That will replace the text in the current line (.*) with Good Morning
    $. is a special Perl variable that holds the current line number of the input file. So, s/foo/bar/ if $.==5, means replace foo with bar only on the 5th line.

  2. sed

    sed -i '5s/.*/ Good Morning /' file{1..4}.txt
    

    Explanation:
    -i : Like for perl, edit file in place.
    By default, sed prints each line of the input file. The 5s/pattern/replacement/ means substitute pattern with replacement on the 5th line.

  3. awk

    for f in file{1..4}.txt; do 
        awk 'NR==5{$0=" Good Morning "}1;' "$f" > foobar && mv foobar "$f"; 
    done
    

    Explanation:
    awk has no equivalent to the -i option1 which means that we need to create a temporary file (foobar) which is then renamed to overwrite the original. The bash loop for f in file{1..4}.txt; do ... ; done simply goes through each of file{1..4}.txt, saving the current file name as $f. In awk, NR is the current line number and $0 is the content of the current line. So, the script will replace the line ($0) with " Good Morning " only on the 5th line. 1; is awk for "print the line".

    1Newer versions do as devnull showed in his answer.

  4. coreutils

    for f in file{1..4}.txt; do 
        (head -4 "$f"; echo " Good Morning "; tail -n +6 "$f") > foobar && 
        mv foobar "$f"; 
    done 
    

    Explanation:
    The loop is explained in the previous section.
    head -4 : print the first 4 lines
    echo " Good Morning ": print " Good Morning "
    tail -n +6 : print everything from the 6th line to the end of the file
    The parentheses ( ) around those three commands allow you to capture the output of all three (so, 1st 4 lines, then " Good morning ", then the rest of the lines) and redirect them to a file.

    `

share|improve this answer

You could use sed:

sed '5s/^/Good morning /' file

would append Good morning on the fifth line of a file.

If you want to replace the contents on line 5 instead, say:

sed '5s/.*/Good morning/' file

If you wanted to save the changes to the file in-place, use the -i option:

sed -i '5s/.*/Good morning/' file

sed can handle more than one file at a time. You can just add more filenames onto the end of the command. You can also use bash expansions to match particular files:

# manually specified
sed -i '5s/.*/Good morning/' file1.txt file2.txt file3.txt file4.txt

# wildcard: all files on the desktop
sed -i '5s/.*/Good morning/' ~/Desktop/*

# brace expansion: file1.txt, file2.txt, file3.txt, file4.txt
sed -i '5s/.*/Good morning/' file{1..4}.txt

You can read more about brace expansions here.


GNU awk versions 4.1.0 and higher come with an extension that enable in-place editing. So you could say:

gawk -i inplace 'NR==5{$0="Good morning"}7' file

to replace line #5 in the file with Good morning!

share|improve this answer

You can use Vim in Ex mode:

for b in 1 2 3 4
do
  ex -sc '5c|Good Morning' -cx file$b.txt
done
  1. 5 select 5th line

  2. c replace text

  3. x save and close

share|improve this answer

The following is a bash script which wraps up the perl process suggested in this answer

Example:

/tmp/it

console:
  enabled:false

Then run the following:

$ search_and_replace_on_line_of_file.sh false true 2 /tmp/it

and the file now contains

/tmp/it

console:
  enabled:true

search_and_replace_on_line_of_file.sh

function show_help()
{
  IT=$(CAT <<EOF

  usage: SEARCH REPLACE LINE_NUM FILE

  e.g. 

  false true 52 /tmp/it  -> replaces false with true on line 52 of file /tmp/it

  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$4" ]
then
  show_help
fi

SEARCH_FOR=$1
REPLACE_WITH=$2
LINE_NO=$3
FILE_NAME=$4
perl -i -pe "s/$SEARCH_FOR/$REPLACE_WITH/ if $.==$LINE_NO" $FILE_NAME 
share|improve this answer

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.