find(dla predykatów -name/ -pathstandardowych) 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 findwyś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 3z niektórymi findimplementacjami). 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 findprzeciwieństwie do globów odczytywałoby zawartość katalogów innych niż foo*barte 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ę, findjeś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 fi większość innych findpredykató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ć oNtam pominąć sortowania jak z find, Daby to kropka pliki (nie stosuje się do tego glob))
¹ Aby findprzeszukiwać 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*bartych, 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).
-pathlub-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?