text file multiply bash linux
for example i have a text file with 5 lines:
one
two
three
four
five
and i want to make a script to make a 2000 lines file containing loops of the file above and it would look like
one
two
three
four
five
one
two
three
four
five
one
two开发者_如何学Go
three
four
five
............repeat until n times is reached
Testing showed this to be about 100 times faster than the next best approach given so far.
#!/bin/bash
IN="${1}"
OUT="${2}"
for i in {1..2000}; do
echo "${IN}"
done | xargs cat > "${OUT}"
The reason this is so much faster is because it doesn't repeatedly open, seek to end, append, and close the output file. It opens the output file once, and streams the data to it in a single large, continuous write. It also invokes cat
as few times as possible. It may invoke cat
only once, even, depending on the system's maximum command line length and the length of the input file name.
If you need to repeat 2000 times
for i in {1..2000}; do cat "FILE"; done > NEW_FILE
Do you need 2000 lines or 2000 copies of the original file?
If the first:
infile='/path/to/inputfile'
outfile='/path/to/outputfile'
len=$(wc -l < "$infile")
for ((i=1; i<=2000/len; i++))
do
cat "$infile"
done > "$outfile.tmp" # you can use mktemp or tempfile if you want
head -n 2000 "$outfile.tmp" > "$outfile"
rm "$outfile.tmp"
If the second:
for i in {1..2000}; do cat "$infile"; done > "$outfile"
For a small input file (avoids the overhead of forking cat
2000 times):
file=$(<"$infile"); for i in {1..2000}; do echo "$file"; done > "$outfile"
Does it need to be a script? If you just want to quickly generate that you can open on vim, cut (press esc than 5dd to cut 5 lines) and than insert n times (press esc than n p to paste n times).
Edit: if you absolutely need a script and efficiency is not a problem, you can do this "dirty" trick:
i=0;
n=5;
while(($i < $n)) ; do
cat orginal_file >> new_file;
let i+=1;
done
file_size() {
cat -- "$@" |wc -l
}
mult_file() {
local \
max_lines="$1" \
iter_size \
iters \
i
shift 1
iter_size="$(file_size "$@")"
let iters=max_lines/iter_size+1
(for ((i=0; i<iters; ++i)); do
cat -- "$@"
done) |
head --lines="$max_lines"
}
mult_file "$@"
So you would call it like script.sh LINES FILE1 FILE2 FILE3 >REPEAT_FILE
.
No process in the loop, no pipes:
infile='5.txt'
outfile='2000.txt'
n=$((2000/ $(wc -l < "$infile") )) # repetitions
> "$outfile" # empty output file
IFS=''
content=$(cat "$infile") # file content as string
for (( CNTR=0; CNTR<n; CNTR+=1 )); do
echo "$content" >> "$outfile"
done
精彩评论