440

I have two files: file1 and file2. How do I append the contents of file2 to file1 so that contents of file1 persist the process?

asir
  • 11,193
  • 8
  • 22
  • 18

8 Answers8

639

Use bash builtin redirection (tldp):

cat file2 >> file1
David
  • 176,566
  • 33
  • 178
  • 245
  • 3
    How do you do it destination file is not owned by you and you need to use sudo? – Bijay Rungta Feb 06 '14 at 19:30
  • 1
    @BijayRungta: It sounds like you answered your own question. You'd pre-pend `sudo` to the `cat` command (and enter credentials if prompted). – David Feb 06 '14 at 19:46
  • you need to ... chmod 777 /etc/default/docker to give yourself write permissions on that file - be sure to restore the old file permissions once done – danday74 Mar 09 '16 at 18:54
  • How to append the same file into 2 files, using one command? Is it possible? Like this: `cat 1 >> 2 3`. – Sigur Sep 30 '17 at 15:40
  • @Sigur: Kind of. You can chain any commands on the shell. So you might do something like this: cat 1 >> 2 && cat 1 >> 3 – David Sep 30 '17 at 16:44
  • @David, so we must use `cat` twice?! – Sigur Sep 30 '17 at 17:30
  • 1
    @Sigur: Unless there’s a way to direct the output to two files at once, it would involve two invocations of the command. – David Sep 30 '17 at 17:45
  • 3
    @Sigur or have a look at the `tee` program: `cat 1 | tee -a 2 3`. You can put as many files as you like after the `--append` (or `-a` for short) switch. – Stefan van den Akker Oct 07 '17 at 15:21
  • This answer does not answer the OP's question to do the append "without overwriting the current file1". You can verify this with the following one-liner: `echo One > file1 && echo Two > file2 && cat file2 >> file1 && cat file1`. As mentioned elsewhere, what OP wants is `cat file1 file2 > file3`. – rinogo Sep 03 '18 at 22:17
299

cat file2 >> file1

The >> operator appends the output to the named file or creates the named file if it does not exist.

cat file1 file2 > file3

This concatenates two or more files to one. You can have as many source files as you need. For example,

cat *.txt >> newfile.txt

Update 20130902
In the comments eumiro suggests "don't try cat file1 file2 > file1." The reason this might not result in the expected outcome is that the file receiving the redirect is prepared before the command to the left of the > is executed. In this case, first file1 is truncated to zero length and opened for output, then the cat command attempts to concatenate the now zero-length file plus the contents of file2 into file1. The result is that the original contents of file1 are lost and in its place is a copy of file2 which probably isn't what was expected.

Update 20160919
In the comments tpartee suggests linking to backing information/sources. For an authoritative reference, I direct the kind reader to the sh man page at linuxcommand.org which states:

Before a command is executed, its input and output may be redirected using a special notation interpreted by the shell.

While that does tell the reader what they need to know it is easy to miss if you aren't looking for it and parsing the statement word by word. The most important word here being 'before'. The redirection is completed (or fails) before the command is executed.

In the example case of cat file1 file2 > file1 the shell performs the redirection first so that the I/O handles are in place in the environment in which the command will be executed before it is executed.

A friendlier version in which the redirection precedence is covered at length can be found at Ian Allen's web site in the form of Linux courseware. His I/O Redirection Notes page has much to say on the topic, including the observation that redirection works even without a command. Passing this to the shell:

$ >out

...creates an empty file named out. The shell first sets up the I/O redirection, then looks for a command, finds none, and completes the operation.

JoshMc
  • 8,846
  • 2
  • 15
  • 34
T.Rob
  • 30,636
  • 9
  • 56
  • 101
  • 17
    @asir - don't try `cat file1 file2 > file1` - this won't work like you are probably awaiting. – eumiro Feb 11 '11 at 13:43
  • 5
    Actually this is exactly what he needs. He says "without overwriting the current file1." The first three answerers have completely ignored this part of the question and suggested a command using `>>` which **will** modify the file `file1`. T.Rob did a far superior job of explaining his answer rather than just racing to submit something that was, in point of fact, incorrect. Based on the text of the question, I believe that `cat file1 file2 > file3` is the appropriate command that @asir was looking for. – dm78 Sep 02 '13 at 15:44
  • Thanks for the kind words, David! What @eumiro points out above but doesn't go into detail on is that the operation to the right of the `>` is executed first. So executing `cat file1 file2 > file1` would first clobber `file1` then attempt to copy the now-zero-length file onto itself. This makes sense when you think about the order in which the operations could and should occur but is subtle enough that it catches many people by surprise. So if nothing else, eumiro and you have prompted a further improvement to the answer. Thanks for that! – T.Rob Sep 02 '13 at 18:57
  • Also **don't** try cat file1 >> file1, this will cause the file to be recursively rewritten, I mistakenly do this and just within a few seconds, 50 million lines have been put in to the file from just previously a few dozen lines. – O.O Mar 20 '17 at 06:56
  • Also, just to make it a bit more concise, if the "new file" already exists, `>>` *appends* to the file and `>` *replaces* the file. – rinogo Sep 03 '18 at 22:19
45

Note: if you need to use sudo, do this:

sudo bash -c 'cat file2 >> file1'

The usual method of simply prepending sudo to the command will fail, since the privilege escalation doesn't carry over into the output redirection.

jdunk
  • 2,386
  • 2
  • 15
  • 19
28

Try this command:

cat file2 >> file1
eumiro
  • 179,099
  • 29
  • 277
  • 252
13

Just for reference, using ddrescue provides an interruptible way of achieving the task if, for example, you have large files and the need to pause and then carry on at some later point:

ddrescue -o $(wc --bytes file1 | awk '{ print $1 }') file2 file1 logfile

The logfile is the important bit. You can interrupt the process with Ctrl-C and resume it by specifying the exact same command again and ddrescue will read logfile and resume from where it left off. The -o A flag tells ddrescue to start from byte A in the output file (file1). So wc --bytes file1 | awk '{ print $1 }' just extracts the size of file1 in bytes (you can just paste in the output from ls if you like).

As pointed out by ngks in the comments, the downside is that ddrescue will probably not be installed by default, so you will have to install it manually. The other complication is that there are two versions of ddrescue which might be in your repositories: see this askubuntu question for more info. The version you want is the GNU ddrescue, and on Debian-based systems is the package named gddrescue:

sudo apt install gddrescue

For other distros check your package management system for the GNU version of ddrescue.

Zorawar
  • 5,509
  • 2
  • 17
  • 40
  • 1
    For the benefit of new users: ddrescue is a GNU tool, but it may not exist on your Linux, Mac or other unix-like system. ddrescue doesn't appear to be required by POSIX or any other standard. –  Aug 19 '14 at 18:49
3

Another solution:

cat file1 | tee -a file2

tee has the benefit that you can append to as many files as you like, for example:

cat file1 | tee -a file2 file3 file3

will append the contents of file1 to file2, file3 and file4.

From the man page:

-a, --append
       append to the given FILEs, do not overwrite
Stefan van den Akker
  • 5,714
  • 7
  • 38
  • 57
0

cat can be the easy solution but that become very slow when we concat large files, find -print is to rescue you, though you have to use cat once.

amey@xps ~/work/python/tmp $ ls -lhtr
total 969M
-rw-r--r-- 1 amey amey 485M May 24 23:54 bigFile2.txt
-rw-r--r-- 1 amey amey 485M May 24 23:55 bigFile1.txt

 amey@xps ~/work/python/tmp $ time cat bigFile1.txt bigFile2.txt >> out.txt

real    0m3.084s
user    0m0.012s
sys     0m2.308s


amey@xps ~/work/python/tmp $ time find . -maxdepth 1 -type f -name 'bigFile*' -print0 | xargs -0 cat -- > outFile1

real    0m2.516s
user    0m0.028s
sys     0m2.204s
Amey Jadiye
  • 2,819
  • 3
  • 22
  • 36
  • The time savings you report for your find/cat combo command is because you are timing the find command only which is printing out the names of the files. Try timing the entire command like this: `time (find . -maxdepth 1 -type f -name 'bigFile*' -print0 | xargs -0 cat -- > outFile1)` and it should product similar results to your cat only command. – JoshMc Mar 14 '17 at 05:29
0

You can also do this without cat, though honestly cat is more readable:

>> file1 < file2

The >> appends STDIN to file1 and the < dumps file2 to STDIN.

Alok Singh
  • 39
  • 1
  • 5