Le but du script que je fais est de comparer deux séries de fichiers. Les noms de fichiers sont eux-mêmes stockés dans deux fichiers distincts, un chemin par ligne. Mon idée est d'avoir deux while read
boucles, une pour chaque liste de noms de fichiers, mais comment mélanger les deux boucles ensemble?
while read compareFile <&3; do
if [[ ! $server =~ [^[:space:]] ]] ; then #empty line exception
continue
fi
echo "Comparing file - $compareFile"
if diff "$compareFile" _(other file from loop?_) >/dev/null ; then
echo Same
else
echo Different
fi
done 3</infanass/dev/admin/filestoCompare.txt
J'ai besoin de pouvoir comparer des fichiers de deux listes différentes en même temps à travers deux boucles de lecture ... Est-ce même possible?
bash
shell-script
control-flow
mkrouse
la source
la source
diff
.diff
.Réponses:
Vous n'avez pas besoin de deux boucles; il vous suffit de lire à partir de deux fichiers dans la même boucle.
la source
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.)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 utilisergrep
pour filtrer les lignes non vides.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é.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.Une autre méthode consiste à écrire une fonction qui se comporte comme
read
mais qui saute les lignes vides. Cette fonction peut fonctionner en appelantread
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 deVARIABLE
; ici, la variable est la variable spéciale#
qui contient le nombre de paramètres positionnels, tout${!#}
comme le dernier paramètre positionnel.la source
-u
option de lectureUne approche serait d'utiliser
read -ra
au lieu de simplementread
. En supposant que lesfilestoCompare.txt
contenus 2 colonnes avec les noms de fichiers dans chacun, leread -ra
lirait les deux colonnes en même temps et les affecter dans un tableau,compareFile
. Ce tableau pourrait alors être accessible de sorte que l'index 0 serait le premier fichier et l'index 1 serait le deuxième fichier à chaque fois dans lawhile
boucle.Exemple
Disons que j'ai ce fichier:,
filestoCompare.txt
et il contient les éléments suivants:La commande pour parcourir ce fichier serait la suivante:
Si les 2 fichiers sont en effet des fichiers distincts tels que:
Ils peuvent être associés à la
paste
commande comme suit:Voici le contenu de list1and2:
la source
join
les d'abord.paste
pour joindre les 2 fichiers? Cela vous amènerait-il à sous-voter?