Możesz być zainteresowany „biedakiem find
”:
shopt -s globstar
shopt -s
s ETS nazwany opcję powłoki (y). globstar
Rozwiązaniem jest zdefiniowany w następujący sposób bash (1) :
Jeśli jest ustawiony, wzorzec **
użyty w kontekście rozszerzenia nazwy pliku / ścieżki będzie pasował do plików [sic] i zero lub więcej katalogów i podkatalogów. Jeśli po wzorcu występuje a /
, tylko katalogi i podkatalogi są zgodne.
Po zakończeniu możesz wykonać shopt -s globstar
dowolne z następujących poleceń:
ls -d1 - source / ** # Znak po „d” jest cyfrą.
ls -d - źródło / ** | cat # tzn. zapisze to w potoku do dowolnego polecenia.
printf "% s \ n" źródło / **
wytworzy wynik:
source/
source/fonts
source/fonts/fontello
source/images
source/images/bg1.png
source/images/eng.png
source/images/fra.png
Niestety dotyczy to również nazw katalogów. To może pomóc trochę wiedzieć, że
printf "%s\n" source/**/
wytworzy wynik:
source/
source/fonts
source/images
tj. tylko nazwy katalogów. Możesz przekierować wyjście jednej z pierwszego zestawu poleceń do jednego pliku, przekierować wyjście powyżej drugiego pliku, a następnie użyć comm
, diff
lub coś podobnego, aby odjąć drugi plik z pierwszego, pozostawiając tylko zwykły pliki (inne niż katalogi). Ale nie rób tego.
Innym podejściem (to niewiele lepsze) jest
ls -d --file-type -- source/** | grep -v '/$'
Ta --file-type
opcja ls
wyświetla /
na końcu nazwy każdego katalogu (i inne znaki na końcu innych (specjalnych) typów plików), na przykład:
source // # Dodano dodatkowy jeden
source / fonts / # Dodano jeden
źródło / fonts / fontello
źródło / obrazy / # Dodano jeden
source / images / bg1.png
source / images / eng.png
source / images / fra.png
a następnie grep -v '/$'
usuwa linie, które kończą się /
; tzn. nazwy katalogów. Niestety --file-type
opcja nie jest określona przez POSIX . Jeśli twoja wersja ls
go nie obsługuje, użyj -F
. To tak, jakby --file-type
wyświetlał również *
na końcach nazw plików wykonywalnych, co dla niektórych osób jest denerwujące. Możesz je wyeliminować za pomocą sed
:
ls -dF -- source/** | sed -e '/\/$/d' -e 's/\*$//'
Jeśli chcesz coś zrobić ze wszystkimi plikami (i tylko plikami), możesz to zrobić
dla f w źródle / **
robić
jeśli [-f "$ f"]
następnie
W tym miejscu wstaw polecenia do zwykłych plików.
fi
gotowy
Uwagi:
- Kiedy
ls
jest wyprowadzanie na terminal, a to nie jest w -l
( l trybie Ong), zapisuje wiele nazw na linię (chyba, że nazwy są bardzo długie). Możesz zmusić go do napisania jednej nazwy w wierszu, określając -1
(jedną) lub przekierowując dane wyjściowe do pliku lub potoku.
- Prawdopodobnie nie naprawdę potrzebne
--
w ls
poleceniach ponieważ jesteś wymieniając katalogu, którego zawartość została utworzona. Powinieneś go używać podczas wpisywania *
do nieznanego katalogu, jako ochronę przed nazwami plików zaczynającymi się od -
.
- Nie próbuj analizować danych wyjściowych
ls
.
- Opcja
globstar
powłoki wydaje się nie być zdefiniowana przez POSIX. (W rzeczywistości nie jestem pewien, czy POSIX rozpoznaje jakiekolwiek opcje powłoki.) Chociaż wydaje się, że jest to bash
ism, uważaj - może nie być obecny we wszystkich wersjach bash.
Jeśli fonts
lub images
ma podkatalogi, **
wyświetli je wszystkie, rekurencyjnie, aż do końca. Jednym (nieco niechlujnym i zawodnym) sposobem ograniczenia głębokości jest
ls -d --file-type -- source/** | grep -v '\(/.*\)\{3\}'
który usuwa wiersze zawierające trzy lub więcej /
znaków.
find
niewłaściwego użycia ; szczególnie, jeśli biegnieszfor file in $(find ...)
, trafiłeś jeden z nich).