find
(dla predykatów -name
/ -path
standardowych) używa wzorców symboli wieloznacznych, podobnie jak globs (zauważ, że {a,b}
nie jest operatorem glob; po rozwinięciu otrzymujesz dwa globusy). Główną różnicą jest obsługa ukośników (oraz plików kropkowych i katalogów, które nie są specjalnie traktowane find
). *
w globach nie obejmuje kilku katalogów. */*/*
spowoduje wyświetlenie maksymalnie 2 poziomów katalogów. Dodanie -path './*/*/*'
spowoduje dopasowanie do plików o głębokości co najmniej 3 poziomów i nie przestanie find
wyświetlać zawartości dowolnego katalogu na dowolnej głębokości.
Do tego konkretnego
./foo*bar/quux[A-Z]{.bak,}/pic[0-9][0-9][0-9][0-9]?.jpg
kilka globów, łatwo to przetłumaczyć, potrzebujesz katalogów na głębokości 3, więc możesz użyć:
find . -mindepth 3 -maxdepth 3 \
\( -path './foo*bar/quux[A-Z].bak/pic[0-9][0-9][0-9][0-9]?.jpg' -o \
-path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg' \) \
-exec cmd {} +
(lub -depth 3
z niektórymi find
implementacjami). Lub POSIXly:
find . -path './*/*/*' -prune \
\( -path './foo*bar/quux[A-Z].bak/pic[0-9][0-9][0-9][0-9]?.jpg' -o \
-path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg' \) \
-exec cmd {} +
Co zagwarantowałoby, że te *
i ?
nie będą pasowały do /
postaci.
(w find
przeciwieństwie do globów odczytywałoby zawartość katalogów innych niż foo*bar
te w bieżącym katalogu¹, a nie sortowało listy plików. Ale pomijając problem, to, co jest dopasowane [A-Z]
lub zachowanie *
/ ?
w odniesieniu do nieprawidłowych znaków jest nieokreślony, otrzymasz tę samą listę plików).
Ale w każdym razie, jak pokazał @muru , nie trzeba uciekać się, find
jeśli chodzi tylko o podzielenie listy plików na kilka przebiegów, aby obejść limit execve()
wywołania systemowego. Niektóre powłoki, takie jak zsh
(z zargs
) lub ksh93
(z command -x
) mają nawet wbudowaną obsługę tego.
Z zsh
(którego globusy mają również odpowiedniki -type f
i większość innych find
predykatów), na przykład:
autoload zargs # if not already in ~/.zshrc
zargs ./foo*bar/quux[A-Z](|.bak)/pic[0-9][0-9][0-9][0-9]?.jpg(.) -- cmd
( (|.bak)
Jest to sprzeczne operator glob do {,.bak}
The (.)
glob kwalifikator jest odpowiednikiem find
„s -type f
, dodać oN
tam pominąć sortowania jak z find
, D
aby to kropka pliki (nie stosuje się do tego glob))
¹ Aby find
przeszukiwać drzewo katalogów tak jak globs, potrzebujesz czegoś takiego:
find . ! -name . \( \
\( -path './*/*' -o -name 'foo*bar' -o -prune \) \
-path './*/*/*' -prune -name 'pic[0-9][0-9][0-9][0-9]?.jpg' -exec cmd {} + -o \
\( ! -path './*/*' -o -name 'quux[A-Z]' -o -name 'quux[A-Z].bak' -o -prune \) \)
To jest przycinanie wszystkich katalogów na poziomie 1, z wyjątkiem foo*bar
tych, i wszystkie na poziomie 2, z wyjątkiem quux[A-Z]
lub quux[A-Z].bak
, a następnie wybierz pic...
te na poziomie 3 (i przycinaj wszystkie katalogi na tym poziomie).
-path
lub-ipath
.find . -path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg'
powinien działać - oprócz tego, że będzie pasował/fooz/blah/bar/quuxA/pic1234d.jpg
. Czy to będzie problem?