Podejście @ meuh jest nieefektywne jak jego -maxdepth 1 podejście pozwala nadal findczytać zawartość katalogów na poziomie 1, aby później je zignorować. Nie będzie również działał poprawnie z niektórymi findimplementacjami (w tym GNU find), jeśli niektóre nazwy katalogów zawierają sekwencje bajtów, które nie tworzą prawidłowych znaków w ustawieniach regionalnych użytkownika (np. Dla nazw plików z innym kodowaniem znaków).
find . \( -name . -o -prune \) -extra-conditions-and-actions
jest bardziej kanonicznym sposobem implementacji GNU -maxdepth 1(lub FreeBSD -depth -2).
Ogólnie rzecz biorąc, to -depth 1chcesz (-mindepth 1 -maxdepth 1 ), ponieważ nie chcesz brać pod uwagę .(głębokość 0), a następnie jest jeszcze prostsze:
find . ! -name . -prune -extra-conditions-and-actions
Dla -maxdepth 2 to staje się:
find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
I tu właśnie występują problemy z nieprawidłowymi postaciami.
Na przykład, jeśli masz katalog o nazwie, Stéphanektóry éjest zakodowany w zestawie znaków iso8859-1 (aka latin1) (bajt 0xe9), jak to było najczęściej w Europie Zachodniej i Ameryce do połowy 2000 roku, to bajt 0xe9 nie jest poprawny znak w UTF-8. Zatem w ustawieniach regionalnych UTF-8 *symbol wieloznaczny (z niektórymi findimplementacjami) nie będzie pasował, Stéphaneponieważ *ma 0 lub więcej znaków, a 0xe9 nie jest znakiem.
$ locale charmap
UTF-8
$ find . -maxdepth 2
.
./St?phane
./St?phane/Chazelas
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
$ find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St?phane/Chazelas/age
./St?phane/Chazelas/gender
./St?phane/Chazelas/address
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
Mój find (gdy dane wyjściowe trafiają do terminala) wyświetla ten nieprawidłowy bajt 0xe9 jak ?wyżej. Widać, że St<0xe9>phane/Chazelasto nie było pruned.
Możesz obejść ten problem, wykonując:
LC_ALL=C find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
Należy jednak pamiętać, że wpływa to na wszystkie ustawienia regionalne findi każdą uruchomioną aplikację (np. Za pośrednictwem-exec predykatów).
$ LC_ALL=C find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St??phane
./St??phane/Chazelas
./John
./John/Smith
Teraz naprawdę dostaję -maxdepth 2 ale é w drugim Stéphane poprawnie zakodowanym w UTF-8 jest wyświetlane jako ??bajty 0xc3 0xa9 (uważane za dwa pojedyncze niezdefiniowane znaki w ustawieniach regionalnych C) kodowania é UTF-8 niedrukowalne znaki w ustawieniach regionalnych C.
A gdybym dodał a -name '????????', otrzymałbym niewłaściwą Stéphane (kodowaną w iso8859-1).
Aby zastosować zamiast dowolnych ścieżek ., wykonaj następujące czynności:
find some/dir/. ! -name . -prune ...
dla -mindepth 1 -maxdepth 1lub:
find some/dir/. \( ! -path '*/./*/*' -o -prune \) ...
dla -maxdepth 2 .
Nadal zrobiłbym:
(cd -P -- "$dir" && find . ...)
Po pierwsze, ponieważ powoduje to, że ścieżki są krótsze, co zmniejsza prawdopodobieństwo zbyt długiego napotkania ścieżki lub listy argumentów zbyt długich , ale także obejścia faktu, że findnie może obsługiwać argumentów arbitralnej ścieżki (z wyjątkiem -fFreeBSD find), ponieważ będzie się dusić wartości $dirjak !lub -print...
W -opołączeniu z negacją jest powszechną sztuczką do uruchamiania dwóch niezależnych zestawów -condition/ -actionin find.
Jeśli chcesz uruchomić -action1na spotkaniu plików -condition1i niezależnie -action2na spotkaniu plików -condition2, nie możesz:
find . -condition1 -action1 -condition2 -action2
Podobnie jak w -action2przypadku plików, które się spełniają oba warunki.
Ani:
find . -contition1 -action1 -o -condition2 -action2
Jak -action2nie będzie działać na plikach, które spełniają oba warunki.
find . \( ! -condition1 -o -action1 \) -condition2 -action2
działa tak, \( ! -condition1 -o -action1 \)jakby rozwiązał prawdę dla każdego pliku. Zakłada się, że -action1to działanie (jak -prune, -exec ... {} +), które zawsze zwraca wartość true . Dla takich działań -exec ... \;może być zwracana wartość false , możesz dodać inną, -o -somethinggdzie -somethingjest nieszkodliwa, ale zwraca wartość true, tak jak -truew GNU findlub -links +0lub -name '*'(choć zwróć uwagę na problem dotyczący nieprawidłowych znaków powyżej).
-depth -2,-depth 1... podejście może być postrzegane jako lepsze niż GNU-maxdepth/-mindepth