Método 1: use o que você sabe
Como você já sabe como fazer o loop de um arquivo, é possível combinar os arquivos e processar os arquivos combinados. O comando paste
une dois arquivos linha por linha. Ele coloca uma tabulação entre as linhas provenientes dos dois arquivos, portanto, esta solução assume que não há guias nos nomes dos arquivos. (Você pode alterar o separador, mas você precisa encontrar um caractere que não esteja presente em um nome de arquivo.)
paste -- "$list1.txt" "list2.txt" |
while IFS=$'\t' read -r file1 file2 rest; do
diff -q -- "$file1" "$file2"
case $? in
0) status='same';;
1) status='different';;
*) status='ERROR';;
esac
echo "$status $file1 $file2"
done
Se você quiser pular linhas em branco, precisará fazer isso em cada arquivo separadamente, pois paste
pode corresponder a uma linha em branco de um arquivo com uma linha não em branco de outro arquivo. Você pode usar grep
para filtrar as linhas não em branco.
paste -- <(grep '[^[:space:]]' "$list1.txt") <(grep '[^[:space:]]' "list2.txt") |
while IFS=$'\t' read -r file1 file2 rest; do
…
Observe que, se os dois arquivos tiverem comprimentos diferentes, você receberá um $file2
vazio (independentemente de qual lista terminou primeiro).
Método 2: faça um loop sobre dois arquivos
Você pode colocar um comando tão complexo quanto desejar na condição do loop while. Se você colocar read file1 <&3 && read file2 <&4
, o loop será executado contanto que os dois arquivos tenham uma linha para ler, ou seja, até que um arquivo acabe.
while read -u 3 -r file1 && read -u 4 -r file2; do
…
done 3<list1..txt 4<list2.txt
Se você quiser pular linhas em branco, é um pouco mais complicado, porque você tem que fazer o salto nos dois arquivos de forma independente. A maneira mais fácil é dividir o problema em duas partes: pule as linhas em branco de um arquivo e processe as linhas não em branco. Um método para pular as linhas em branco é processar através de grep
como acima. Observe o espaço necessário entre o operador de redirecionamento <
e o <(
que inicia uma substituição de comando.
while read -u 3 -r file1 && read -u 4 -r file2; do
…
done 3< <(grep '[^[:space:]]' "$list1.txt") 4< <(grep '[^[:space:]]' "list2.txt")
Outro método é escrever uma função que se comporta como read
, mas ignora linhas em branco. Esta função pode funcionar chamando read
em um loop. Não precisa ser uma função, mas uma função é a melhor abordagem, tanto para organizar seu código quanto porque essa parte do código precisa ser chamada duas vezes. Na função, ${!#}
é uma instância da construção bash ${!VARIABLE}
que avalia o valor da variável cujo nome é o valor de VARIABLE
; aqui a variável é a variável especial #
que contém o número do parâmetro posicional, então ${!#}
é o último parâmetro posicional.
function read_nonblank {
while read "$@" &&
[[ ${!#} !~ [^[:space:]] ]]
do :; done
}
while read_nonblank -u 3 -r file1 && read_nonblank -u 4 -r file2; do
…
done 3<list1..txt 4<list2.txt