Méthode 1: utilisez ce que vous savez
Comme vous savez déjà comment boucler sur un fichier, vous pouvez combiner les fichiers, puis traiter les fichiers combinés. La commande paste
joint deux fichiers ligne par ligne. Il met un onglet entre les lignes provenant des deux fichiers, donc cette solution suppose qu'il n'y a pas d'onglets dans vos noms de fichiers. (Vous pouvez changer le séparateur mais vous devez trouver un caractère qui n'est pas présent dans un nom de fichier.)
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
Si vous souhaitez ignorer les lignes vides, vous devez le faire dans chaque fichier séparément, car il paste
peut correspondre à une ligne vierge d'un fichier avec une ligne non vide d'un autre fichier. Vous pouvez utiliser grep
pour filtrer les lignes non vides.
paste -- <(grep '[^[:space:]]' "$list1.txt") <(grep '[^[:space:]]' "list2.txt") |
while IFS=$'\t' read -r file1 file2 rest; do
…
Notez que si les deux fichiers ont des longueurs différentes, vous obtiendrez un vide $file2
(quelle que soit la liste terminée en premier).
Méthode 2: boucle sur deux fichiers
Vous pouvez mettre une commande aussi complexe que vous le souhaitez dans la condition de la boucle while. Si vous le mettez, read file1 <&3 && read file2 <&4
la boucle s'exécutera tant que les deux fichiers auront une ligne à lire, c'est-à-dire jusqu'à ce qu'un fichier soit épuisé.
while read -u 3 -r file1 && read -u 4 -r file2; do
…
done 3<list1..txt 4<list2.txt
Si vous voulez sauter des lignes vides, c'est un peu plus compliqué, car vous devez faire le saut dans les deux fichiers indépendamment. Le moyen le plus simple consiste à diviser le problème en deux parties: ignorer les lignes vierges d'un fichier et traiter les lignes non vides. Une méthode pour sauter les lignes vides consiste à procéder grep
comme ci-dessus. Méfiez-vous de l'espace nécessaire entre l' <
opérateur de redirection et celui <(
qui démarre une substitution de commande.
while read -u 3 -r file1 && read -u 4 -r file2; do
…
done 3< <(grep '[^[:space:]]' "$list1.txt") 4< <(grep '[^[:space:]]' "list2.txt")
Une autre méthode consiste à écrire une fonction qui se comporte comme read
mais qui saute les lignes vides. Cette fonction peut fonctionner en appelant read
en boucle. Il n'est pas nécessaire que ce soit une fonction, mais une fonction est la meilleure approche, à la fois pour organiser votre code et parce que ce morceau de code doit être appelé deux fois. Dans la fonction, ${!#}
est une instance de la construction bash ${!VARIABLE}
qui évalue la valeur de la variable dont le nom est la valeur de VARIABLE
; ici, la variable est la variable spéciale #
qui contient le nombre de paramètres positionnels, tout ${!#}
comme le dernier paramètre positionnel.
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
.