-1

I have two files file1 containing -

hello world
hello bangladesh  

and file2 containing -

Dhaka in Bangladesh
Dhaka is capital of Bangladesh  

I want to new file2 as -

hello world
hello bangladesh 
Dhaka in Bangladesh
Dhaka is capital of Bangladesh

This is done by -

cat file1 file2 >> file3
mv file3 file2  

But, I don't want to create new file. I guess using sed it may be possible.

Joe
  • 41,484
  • 20
  • 104
  • 125
  • Simply write `cat file1 file2 >> file2`? works fine for me on my console – SourceOverflow Jan 03 '18 at 01:30
  • 1
    @SourceOverflow: Are you sure about that? I got an error message "`cat: file2: input file is output file`". Perhaps you meant to write `cat file1 >> file2` -- but that would append the content of `file1` to the end of `file2`. The OP wants to insert the content of `file1` at the top of `file2`. – Keith Thompson Jan 03 '18 at 01:39
  • @KeithThompson nope I did it exactly as I described. I got the 'error' (warning?) too, but it still worked. I can't guarantee that that is always the case for every interpreter and that there are no race conditions (which is why I just posted a comment) – SourceOverflow Jan 03 '18 at 01:42
  • @SourceOverflow: Sorry, when I saw the error message I didn't bother to check the file contents. But when I ran the command on my system (using bash 4.4.0), the lines in `file2` were in the wrong order. (My head hurts trying to figure out just what happened.) – Keith Thompson Jan 03 '18 at 01:49
  • @KeithThompson Probably some sort of race condition? idk to be honest :/ – SourceOverflow Jan 03 '18 at 01:57
  • @SourceOverflow Then if people can confused viewing your 1st comment. –  Jan 03 '18 at 02:12
  • See https://stackoverflow.com/a/17331179/1745001 – Ed Morton Jan 04 '18 at 04:37

2 Answers2

1

Sure it's possible.

printf '%s\n' '0r file1' x | ex file2

This is a POSIX-compliant command using ex, the POSIX-specified non-visual predecessor to vi.

printf is only used here to feed a command to the editor. What printf outputs is:

0r file1
x

x is save and exit.

r is "read in the contents of the named file."

0 specifies the line number after which the read-in text should be placed.

N.B. This answer is fully copied from Is it possible to add some text at beginning of a file in CLI without making new file?

Another solution
There aren't a lot of ways to modify files in place using standard tools. Even if they appear to do so they may be using temporary files (i.e. GNU sed -i).

ex on the other hand, will do the trick:

ex +'0r file2' +wq file1

ex is a line editor and vim evolved from it so these commands may look familiar. 0r filename does the same thing as :0r filename in vim: insert the specified file after the given address (line number). The line number here is 0 which is a kind of virtual line that represents the line before line 1. So the file will be inserted before any existing text.

Then we have wq which saves and quits.

That's it.

N.B. This answer is fully copied from https://unix.stackexchange.com/a/414408/176227

  • Nice. I would have expected `ex` to create a new file, but (at least on my system, with the `ex` provided by Vim 8.0) it overwrites the original file, leaving it with the same inode number. Doing the equivalent with `vim` creates a new file. – Keith Thompson Jan 03 '18 at 02:13
  • `ex` creates an internal buffer the size of the input file so if you're trying to avoid creating a temp file for memory reasons then YMMV! You can do the same thing with awk by reading all of the input into an array, closing the input file, then writing it back out in the END section. I expect GNU sed at least has some combination of runes that'd let it do the same. The way to do it without buffering the whole file is described at https://stackoverflow.com/a/17331179/1745001. – Ed Morton Jan 04 '18 at 04:34
0

You want to insert two lines at the top of an existing file.

There's no general way to do that. You can append data to the end of an existing file, but there's no way to insert data other than at the end, at least not without rewriting the portion of the file after the insertion point.

Once a file has been created, you can overwrite data within it, but the position of any unmodified data remains the same.

When you use a text editor to edit a file, it performs the updates in memory; when you save the file, it may create a new file with the same name as the old one, or it may create a temporary file and then rename it. either way, it has to write the entire content, and the original file will be clobbered (though some editors may create a backup copy).

Your method:

cat file1 file2 >> file3
mv file3 file2

is pretty much the way to do it (except that the >> should be >; you don't want to retain the previous contents of file3 if it already exists).

You can use a temporary file name:

cat file1 file2 > tmp$$ && mv tmp$$ file2

tmp$$ uses the current shell's process ID to generate a file name that's almost certain to be unique (so you don't clobber anything). The && means that the mv command won't be executed if the cat command failed, so that you'll still have the original file2 if there was an error.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631