Bash: Two for loops at once?
Bash: Two for loops at once?
I am not sure how to do this at all.
I have two text files, FILE1
and FILE2
.
FILE1
FILE2
I would like to run a for loop for each file at the same time and display the
contents next to each other.
For example,
for $i in $(cat FILE1); do echo $i; done
for $i in $(cat FILE1); do echo $i; done
for $j in $(cat FILE2); do echo $j; done
for $j in $(cat FILE2); do echo $j; done
I would like to combine these two commands, so I can run both files at the same time and have an output like $i $j
$i $j
paste
If you don't want
paste
(though I guess you do) maybe look at Looping over pairs of values in Bash– tripleee
Aug 18 at 5:51
paste
5 Answers
5
Solution 1
Use the paste
command
paste
paste FILE1 FILE2
paste FILE1 FILE2
Details for paste command
Another resource
Solution 2
You can do this if they have the same number of lines.
#!/bin/bash
t=$(cat FILE1 | wc -l)
for i in `seq 1 $t`;
do
cat FILE1|head -n $i|tail -n 1
cat FILE2|head -n $i|tail -n 1
done
You can extend it to what you want for unequal number of lines.
Solution 2 is horribly inefficient, and should never be used.
– chepner
Aug 18 at 13:13
You shouldn't be using for
loops at all; see Bash FAQ 001. Instead, use two read
commands in a single while
loop.
for
read
while
while IFS= read -r line1 && IFS= read -r line2 <&3; do
printf '%s | %sn' "$line1" "$line2"
done < FILE1 3< FILE2
Each read
command reads from a separate file descriptor. In this version, the loop will exit when the shorter of the two files is exhausted.
read
I wish I could upvote this more than once.
– keithpjolley
Aug 18 at 13:23
There are two different questions being asked here. Other answers address the question of how to display the contents of the file in 2 columns. Running two loops simultaneously (which is the wrong way to address the first problem) can be done by running them each asynchronously: for i in $seqi?; do $cmdi?; done & for j in $seqj?; do $cmdj?; done & wait
for i in $seqi?; do $cmdi?; done & for j in $seqj?; do $cmdj?; done & wait
Although you could also implement paste -d ' ' file1 file2
with something like:
paste -d ' ' file1 file2
while read line_from_file1; p=$?; read line_from_file2 <&3 || test "$p" = 0; do
echo "$line_from_file1" "$line_from_file2"
done < file1 3< file2
I just noticed that @chepner gave nearly this same solution, but I'll not delete mine since it addresses the issue of the files having different line lenghts. But this is totally a hack and should never be done.
– William Pursell
Aug 18 at 13:31
Another option, in bash
v4+ is to read the two files into 2 arrays, then echo the array elements side-by-side:
bash
# Load each file into its own array
readarray -t f1 < file1
readarray -t f2 < file2
# Print elements of both arrays side-by-side
for ((i=0;i<$#f1[@];i++)) ; do echo $f1[i] $f2[i]; done
Or change the echo
to printf
if you want the columns to line up:
echo
printf
printf "%-20s %-20sn" $f1[i] $f2[i]
I'm not suggesting you do this if your files are 100s of megabytes.
You can use another tab by pressing Command T and then run the each bash script on another tab.
Thank you.
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
That is precisely what
paste
does.– rici
Aug 18 at 5:25