If you know for sure that some character will never occur in both files then you can use paste.
Example of paste using default delimiter tab:
paste file1 file2 | while IFS="$(printf '\t')" read -r f1 f2
do
printf 'f1: %s\n' "$f1"
printf 'f2: %s\n' "$f2"
done
Example of paste using @:
paste -d@ file1 file2 | while IFS="@" read -r f1 f2
do
printf 'f1: %s\n' "$f1"
printf 'f2: %s\n' "$f2"
done
Note that it is enough if the character is guaranteed to not occur in the first file. This is because read will ignore IFS when filling the last variable. So even if @ occurs in the second file it will not be split.
Example of paste using some bash features for arguably cleaner code:
while IFS=$'\t' read -r f1 f2
do
printf 'f1: %s\n' "$f1"
printf 'f2: %s\n' "$f2"
done < <(paste file1 file2)
Bash features used: ansi c string ($'\t') and process substitution (<(...)) to avoid the while loop in a subshell problem.
If you cannot be certain that any character will never occur in both files then you can use file descriptors.
while true
do
read -r f1 <&3 || break
read -r f2 <&4 || break
printf 'f1: %s\n' "$f1"
printf 'f2: %s\n' "$f2"
done 3<file1 4<file2
Not tested much. Might break on empty lines.
File descriptors number 0, 1, and 2 are already used for stdin, stdout, and stderr, respectively. File descriptors from 3 and up are (usually) free. The bash manual warns from using file descriptors greater than 9, because they are "used internally".
Note that open file descriptors can be read by anyone so you should close them as soon as you don't need them anymore.
prog() {
printf 'f1: %s\n' "$1"
printf 'f2: %s\n' "$2"
# here we try read from fd3
read -r yoink <&3 && printf 'yoink: %s\n' "$yoink"
}
while true
do
read -r f1 <&3 || break
read -r f2 <&4 || break
# this will close fd3 and fd4 before executing prog
prog "$f1" "$f2" 3<&- 4<&-
# note that fd3 and fd4 are still open in the loop
done 3<file1 4<file2
This is an example output if run without closing the file descriptors (without this part: 3<&- 4<&-):
f1: file1 line1
f2: file2 line1
yoink: file1 line2
f1: file1 line3
f2: file2 line2