Chcę działać na liście podkatalogów w katalogu. Rozważać:
for x in x86-headers/*/C/populate.sh; do echo $x; done
To daje
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
Ale chcę wartości, która odpowiada drugiej części ścieżki
elf
, gl
itp wiem jak rozebrać wiodącym x86-headers
.
for x in x86-headers/*/C/populate.sh; do i=${x##x86-headers/}; echo $i; done
co daje
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
Wiem też, jak zrzucić późniejsze warunki na ścieżce. Tj. Schodzę o jeden poziom:
cd x86-headers
for x in */C/populate.sh; do i=${x%%/*}; echo $i; done
daje
elf
gl
gmp
gnome2
gtk2
jni
libc
Ale próba połączenia ich nie działa. To znaczy
for x in x86-headers/*/C/populate.sh; do i=${${x##x86-headers}%%/*}; echo $i; done
daje
bash: ${${x##x86-headers}%%/*}: bad substitution
Bez wątpienia jest to niepoprawna składnia, ale nie znam poprawnej składni. Oczywiście mogą być na to lepsze sposoby. Gdybym używał Pythona, użyłbym podziału, /
aby podzielić każdą ścieżkę na listę, a następnie wybrać drugi element, ale nie wiem, jak to zrobić w bash.
EDYCJA: Dzięki za odpowiedzi. Powinienem również zapytać, czy można to zrobić przenośnie, a jeśli tak, to w jaki sposób?
i=${x#*/}; i=${i%%/*}
jest opcjonalny, prawda?ash
/dash
, uruchamiałyby przypisania od prawej do lewej (tak zachowywała się powłoka Bourne'a) i powodowały problem w tym przypadku.Rozszerzanie parametrów nie pozwala na zagnieżdżanie wyrażeń, więc musisz to zrobić w dwóch krokach, z przypisaniem:
Masz tutaj opcję użycia tablic, ale sądzę, że byłoby to bardziej kłopotliwe niż powyższy PE:
Jest też trzecia opcja korzystania z zewnętrznych poleceń. Z krótką listą plików jest to zazwyczaj najmniej wydajna opcja, ale będzie skalować się najlepiej w miarę wzrostu liczby plików:
źródło
zsh
pozwala na zagnieżdżanie.bash
.źródło
Bądź bardzo ostrożny, używając poniższego konstruktu:
Jak możesz to zrobić
echo *
. W tym przypadku jest to tylko zabawne, ale mogło być znacznie najgorszy jeśli są korzeń, twojeCWD
znaczy/
i chcesz usunąć niektóre katalogi sub/tmp
zamiast je echem!Aby to naprawić w bash, możesz:
Zwróć uwagę
shopt -u nullglob
na końcu, aby przywrócić domyślne zachowanie bash po pętli.Bardziej przenośnym rozwiązaniem może być:
( Podstawienia
##
i%%
podstawienia parametrów są poprawne w ksh88 ).Kliknij ten link, aby uzyskać pełniejszą dyskusję o nullglob .
Zauważ, że powyższe 3 rozwiązania zawodzą, jeśli masz katalog pośredni ze spacją w nazwie. Aby go rozwiązać, użyj podwójnych cudzysłowów w podstawieniu zmiennej:
źródło
Aby przenośnie dopasowywać wzorce do nazw ścieżek, możesz ustawić
IFS
zmienną powłoki na,/
a następnie użyć rozszerzenia parametrów powłoki.Wykonanie tego wszystkiego w podpowłoce pomaga utrzymać środowisko powłoki nadrzędnej bez zmian!
źródło