Ich möchte auf eine Liste von Unterverzeichnissen in einem Verzeichnis reagieren. Erwägen:
for x in x86-headers/*/C/populate.sh; do echo $x; done
Das gibt
x86-headers/elf/C/populate.sh
x86-headers/gl/C/populate.sh
x86-headers/gmp/C/populate.sh
x86-headers/gnome2/C/populate.sh
x86-headers/gtk2/C/populate.sh
x86-headers/jni/C/populate.sh
x86-headers/libc/C/populate.sh
Aber ich will Werte , dass entspricht dem zweiten Teil des Weges
elf
, gl
usw. Ich weiß , wie die führende abzustreifen x86-headers
.
for x in x86-headers/*/C/populate.sh; do i=${x##x86-headers/}; echo $i; done
was gibt
elf/C/populate.sh
gl/C/populate.sh
gmp/C/populate.sh
gnome2/C/populate.sh
gtk2/C/populate.sh
jni/C/populate.sh
libc/C/populate.sh
Ich weiß auch, wie ich spätere Begriffe auf dem Weg entfernen kann. Dh eine Ebene runter gehen:
cd x86-headers
for x in */C/populate.sh; do i=${x%%/*}; echo $i; done
gibt
elf
gl
gmp
gnome2
gtk2
jni
libc
Der Versuch, diese zu kombinieren, funktioniert jedoch nicht. Dh
for x in x86-headers/*/C/populate.sh; do i=${${x##x86-headers}%%/*}; echo $i; done
gibt
bash: ${${x##x86-headers}%%/*}: bad substitution
Zweifellos ist dies eine falsche Syntax, aber ich kenne die richtige Syntax nicht. Natürlich könnte es bessere Möglichkeiten geben, dies zu tun. Wenn ich Python verwenden würde, würde ich split on verwenden /
, um jeden Pfad in eine Liste zu unterteilen und dann das zweite Element auszuwählen, aber ich weiß nicht, wie ich das in bash machen soll.
EDIT: Danke für die Antworten. Ich hätte auch fragen sollen, ob es möglich ist, dies portabel zu machen, und wenn ja, wie?
i=${x#*/}; i=${i%%/*}
ist optional, oder?ash
/dash
würden die Zuweisungen von rechts nach links ausführen (so hat sich die Bourne-Shell verhalten) und in diesem Fall Probleme verursachen.Durch die Parametererweiterung können Sie keine Ausdrücke verschachteln, daher müssen Sie dies in zwei Schritten mit einer Zuweisung tun:
Sie haben hier die Möglichkeit, Arrays zu verwenden, aber ich würde denken, dass dies umständlicher ist als das obige PE:
Dann gibt es die dritte Möglichkeit, externe Befehle zu verwenden. Bei einer kurzen Liste von Dateien ist dies normalerweise die am wenigsten effiziente Option, aber sie skaliert am besten, wenn die Anzahl der Dateien zunimmt:
quelle
zsh
erlaubt das Verschachteln.bash
.quelle
Seien Sie sehr vorsichtig, wenn Sie ein Konstrukt wie folgt verwenden:
Wie Sie wollen, könnten Sie am Ende eine
echo *
. In diesem Fall ist es nur lustig, aber es könnte viel schlimmer sein, wenn Sie root sind, IhrCWD
is/
und Sie einige Unterverzeichnisse löschen möchten,/tmp
anstatt sie zu wiederholen!Um dies in Bash zu beheben, können Sie Folgendes tun:
Beachten Sie das
shopt -u nullglob
am Ende, um das Standard-Bash-Verhalten nach der Schleife wiederherzustellen.Eine tragbarere Lösung könnte sein:
(Die
##
und%%
Parameter-Ersetzungen sind in ksh88 gültig ).Folgen Sie diesem Link für eine ausführlichere Diskussion von nullglob .
Beachten Sie, dass die drei oben genannten Lösungen fehlschlagen, wenn Sie ein Zwischenverzeichnis mit einem Leerzeichen im Namen haben. Verwenden Sie zur Lösung doppelte Anführungszeichen in der Variablensubstitution:
quelle
Um den Mustervergleich für Pfadnamen portabel durchzuführen, können Sie die
IFS
Shell-Variable auf setzen/
und dann die Shell-Parametererweiterung verwenden.Wenn Sie dies alles in einer Subshell tun, bleibt die Umgebung der übergeordneten Shell unverändert!
quelle