Reputation: 716
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
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
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
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
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
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