
Angenommen, ich habe 2 separate Schleifen
for file1 in `ls Dir1/` ; do
echo $file1
done
for file2 in `ls Dir2/` ; do
echo $file2
done
Ich möchte eine einzelne Schleife, um beide Verzeichnisse Pseudocode zu iterieren
for file1 , file2 in `ls Dir1` , `ls Dir2`
do
echo $file1
echo file2
done
Ist es möglich
Antwort1
Eine while
Schleife mit geeigneter Eingabe kann die Aufgabe erledigen, vorausgesetzt, die Dateinamen enthalten keine Zeilenumbruchzeichen.
paste -d/ <(ls /var) <(ls /usr) |
while IFS=/ read -r e u; do
printf '%s\n' "$e $u"
done
Antwort2
shopt -s nullglob
dir1names=( Dir1/* )
dir2names=( Dir2/* )
while [ "${#dir1names[@]}" -gt 0 ] &&
[ "${#dir2names[@]}" -gt 0 ]
do
printf '%s\n' "${dir1names[0]##*/}"
printf '%s\n' "${dir2names[0]##*/}"
dir1names=( "${dir1names[@]:1}" )
dir2names=( "${dir2names[@]:1}" )
done
Dies dient bash
dazu, alle Pfadnamen aus jedem Verzeichnis in zwei Arrays zu übertragen. Anschließend wird der Dateinamenteil dieser Pfadnamen (wie ls
üblich) abwechselnd zwischen den Arrays gedruckt und die gedruckten Einträge aus den Arrays gelöscht. Es wird beendet, wenn eines der Arrays vollständig leer ist.
Die nullglob
Shell-Option bewirkt, dass nicht übereinstimmende Globbing-Muster ins Leere expandiert werden, anstatt unerweitert zu bleiben.
Testen:
$ tree
.
|-- Dir1
| |-- file-1
| |-- file-2
| |-- file-3
| `-- file-4
|-- Dir2
| |-- otherfile-1
| |-- otherfile-2
| |-- otherfile-3
| |-- otherfile-4
| |-- otherfile-5
| `-- otherfile-6
`-- script.sh
2 directories, 11 files
$ bash script.sh
file-1
otherfile-1
file-2
otherfile-2
file-3
otherfile-3
file-4
otherfile-4
Wenn das istGenau genommenüber das Paaren von Dateien nach ihren Namen, so dass eine Datei in einem Verzeichnis mit der entsprechenden Datei in einem anderen gepaart wird (wie es manchmal in z. B. Bioinformatik-Anwendungen gemacht wird, scheint es), dann ist es besser, einfach über einen der Sätze zu iterieren und dannkonstruierender Name der entsprechenden Dateien aus dem anderen Set.
Angenommen, die Dateien heißen something_R1_more
und geben something_R2_more
dort den Namen an something
und more
identifizieren ein bestimmtes R1
Dateipaar R2
.
for r1 in dir1/*_R1_*; do
r2=${r1##*/} # dir1/something_R1_more --> something_R1_more
r2=dir2/${r2/_R1_/_R2_} # something_R1_more --> dir2/something_R2_more
if [ ! -f "$r2" ]; then
printf '%s not found\n' "$r2" >&2
exit 1
fi
# process "$r1" and "$r2" here
done
Antwort3
Sie im Allgemeinenmöchte die Ausgabe nicht analysieren vonls
.
Hier könnten Sie mit zsh
(Sie verwenden bereits zsh
Syntax, nicht bash
weil Sie Ihre Variablen nicht in Anführungszeichen setzen und Befehlsersetzung verwenden, ohne Globbing zu deaktivieren) Folgendes tun:
dir1_file_names=(dir1/*(N:t))
dir2_file_names=(dir2/*(N:t))
for f1 f2 (${dir1_file_names:^dir2_file_names})
printf '%s\n' "f1: $f1, f2: $f2"
zsh
kann mit mehreren Variablen schleifen. ${a:^b}
ist einArray-KomprimierungOperator. Wenn eines der Arrays weniger Elemente als das andere hat, ist es so, als wären sie auf die Länge des kleinsten Elements gekürzt.
Siehe auch die Array-Schnittpunkt- und Subtraktionsoperatoren, wenn es um den Vergleich der Dateinamen in den beiden Verzeichnissen geht:
file_names_in_both_dir1_and_dir2=(${dir1_file_names:*dir2_file_names})
file_names_only_in_dir1=(${dir1_file_name:|dir2_file_names})
file_names_only_in_dir2=(${dir2_file_name:|dir1_file_names})
Antwort4
Die Ausgabe mehrerer Variablen kann in einer einzigen Variable gespeichert werden, wie unten beschrieben. Überprüfen Sie, ob es für Sie funktioniert
#!/bin/bash
cd /
for file1 in $(ls /usr/ ; echo "::::::NEXT:::::::" ; ls /sys/)
do
echo $file1
done