deep
deep

Reputation: 716

Copy a txt file twice to a different file using bash

I am trying to cat a file.txt and loop it twice through the whole content and copy it to a new file file_new.txt. The bash command I am using is as follows:

for i in {1..3}; do cat file.txt > file_new.txt; done

The above command is just giving me the same file contents as file.txt. Hence file_new.txt is also of the same size (1 GB).

Basically, if file.txt is a 1GB file, then I want file_new.txt to be a 2GB file, double the contents of file.txt. Please, can someone help here? Thank you.

Upvotes: 2

Views: 1869

Answers (5)

William Pursell
William Pursell

Reputation: 212248

As others have mentioned, you can use >> to append. But, you could also just invoke cat once and have it read the file 3 times. For instance:

n=3; cat $( yes file.txt | sed ${n}q ) > file_new.txt

Note that this solution exhibits a common anti-pattern and fails to properly quote the arguments, which will cause issues if the filename contains whitespace. See mklement's solution for a more robust solution.

Upvotes: 0

signjing
signjing

Reputation: 98

if file.txt is a 1GB file, cat file.txt > file_new.txt cat file.txt >> file_new.txt The > operator will create file_new.txt(1GB),
The >> operator will append file_new.txt(2GB).

for i in {1..3}; do cat file.txt >> file_new.txt; done This command will make file_new.txt(3GB),because for i in {1..3} will run three times.

Upvotes: 0

mklement0
mklement0

Reputation: 437988

Simply apply the redirection to the for loop as a whole:

for i in {1..3}; do cat file.txt; done > file_new.txt

The advantage of this over using >> (aside from not having to open and close the file multiple times) is that you needn't ensure that a preexisting output file is truncated first.


Note that the generalization of this approach is to use a group command ({ ...; ...; }) to apply redirections to multiple commands; e.g.:

$ { echo hi; echo there; } > out.txt; cat out.txt
hi
there

Given that whole files are being output, the cost of invoking cat for each repetition will probably not matter that much, but here's a robust way to invoke cat only once:[1]

# Create an array of repetitions of filename 'file' as needed.
files=(); for ((i=0; i<3; ++i)); do files[i]='file'; done
# Pass all repetitions *at once* as arguments to `cat`.
cat "${files[@]}" > file_new.txt

[1] Note that, hypothetically, you could run into your platform's command-line length limit, as reported by getconf ARG_MAX - given that on Linux that limit is 2,097,152 bytes (2MB) that's not likely, though.

Upvotes: 4

Carter Brainerd
Carter Brainerd

Reputation: 197

You should adjust your code so it is as follows:

for i in {1..3}; do cat file.txt >> file_new.txt; done

The >> operator appends data to a file rather than writing over it (>)

Upvotes: 0

donjuedo
donjuedo

Reputation: 2505

You could use the append operator, >>, instead of >. Then adjust your loop count as needed to get the output size desired.

Upvotes: 3

Related Questions