Podejście @ meuh jest nieefektywne jak jego -maxdepth 1
podejście pozwala nadal find
czytać zawartość katalogów na poziomie 1, aby później je zignorować. Nie będzie również działał poprawnie z niektórymi find
implementacjami (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 1
chcesz (-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éphane
któ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 find
implementacjami) nie będzie pasował, Stéphane
ponieważ *
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/Chazelas
to nie było prune
d.
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 find
i 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 1
lub:
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 find
nie może obsługiwać argumentów arbitralnej ścieżki (z wyjątkiem -f
FreeBSD find
), ponieważ będzie się dusić wartości $dir
jak !
lub -print
...
W -o
połączeniu z negacją jest powszechną sztuczką do uruchamiania dwóch niezależnych zestawów -condition
/ -action
in find
.
Jeśli chcesz uruchomić -action1
na spotkaniu plików -condition1
i niezależnie -action2
na spotkaniu plików -condition2
, nie możesz:
find . -condition1 -action1 -condition2 -action2
Podobnie jak w -action2
przypadku plików, które się spełniają oba warunki.
Ani:
find . -contition1 -action1 -o -condition2 -action2
Jak -action2
nie 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 -action1
to 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 -something
gdzie -something
jest nieszkodliwa, ale zwraca wartość true, tak jak -true
w GNU find
lub -links +0
lub -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