Método 1: use o que você sabe
Como você já sabe fazer um loop sobre um arquivo, você pode combinar os arquivos e depois processá-los. O comando paste
une dois arquivos linha por linha. Ele coloca uma guia 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 precisa encontrar um caractere que não esteja presente no nome de um 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á fazê-lo em cada arquivo separadamente, pois paste
pode corresponder 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 que não estã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ê ficará vazio $file2
(independentemente da lista que terminou primeiro).
Método 2: 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 enquanto os dois arquivos tiverem uma linha para ler, ou seja, até que um arquivo se esgote.
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 é necessário pular os 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 que não estiverem em branco. Um método para ignorar as linhas em branco é processar grep
como acima. Cuidado com o espaço necessário entre o <
operador de redirecionamento e o <(
que inicia uma suspeita 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 comporte como, read
mas pule linhas em branco. Esta função pode funcionar chamando read
um loop. Não precisa ser uma função, mas uma função é a melhor abordagem, para organizar seu código e porque esse trecho de código precisa ser chamado duas vezes. Na função, ${!#}
é uma instância do construto 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 de parâmetro posicional, assim ${!#}
como 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
diff
.