Więc następujące zachowanie unixa kosztuje mnie bardzo drogo:
> touch foo
> touch bar
> ls
bar foo
> find . -name '*oo' -delete
> ls
bar
> touch baz
> ls
bar baz
> find . -delete -name '*ar'
> ls
> #WHAAAT?
Jak to ma sens?
Więc następujące zachowanie unixa kosztuje mnie bardzo drogo:
> touch foo
> touch bar
> ls
bar foo
> find . -name '*oo' -delete
> ls
bar
> touch baz
> ls
bar baz
> find . -delete -name '*ar'
> ls
> #WHAAAT?
Jak to ma sens?
Odpowiedzi:
Wiersz polecenia find zawiera różne opcje, które są łączone w wyrażenia.
find
Opcja -delete
jest działaniem.
Oznacza to, że jest wykonywany dla każdego pasującego do tej pory pliku.
Jako pierwsza opcja po ścieżkach wszystkie pliki są dopasowane ... Ups!
Jest to niebezpieczne - ale strona podręcznika ma przynajmniej duże ostrzeżenie :
Od man find
:
ACTIONS
-delete
Delete files; true if removal succeeded. If the removal failed, an
error message is issued. If -delete fails, find's exit status will
be nonzero (when it eventually exits). Use of -delete automatically
turns on the -depth option.
Warnings: Don't forget that the find command line is evaluated as an
expression, so putting -delete first will make find try to delete
everything below the starting points you specified. When testing a
find command line that you later intend to use with -delete, you
should explicitly specify -depth in order to avoid later surprises.
Because -delete implies -depth, you cannot usefully use -prune and
-delete together.
Z dalszej części man find
:
EXPRESSIONS
The expression is made up of options (which affect overall operation rather
than the processing of a specific file, and always return true), tests
(which return a true or false value), and actions (which have side effects
and return a true or false value), all separated by operators. -and is
assumed where the operator is omitted.
If the expression contains no actions other than -prune, -print is per‐
formed on all files for which the expression is true.
Po wypróbowaniu, co find
zrobi polecenie:
Aby zobaczyć, jak lubi polecenie
find . -name '*ar' -delete
usunie, możesz najpierw zastąpić akcję -delete
bardziej nieszkodliwym działaniem - takim jak -fls
lub -print
:
find . -name '*ar' -print
Spowoduje to wydrukowanie plików, na które akcja ma wpływ.
W tym przykładzie -print można pominąć. W tym przypadku, nie ma działania w ogóle, więc najbardziej oczywistym jest dodawane domyślnie: -print
. (Zobacz akapit drugi w sekcji „WYRAŻENIA” cytowanej powyżej)
-delete
flagę :-) Ale czy istnieje jakiś powód, by ktoś kiedykolwiek zrobić find . -delete
zamiast rm -rf .
? A może tak właśnie się dzieje, gdy find
analizuje i przetwarza swoje argumenty?
warning: use -depth when testing stuff you later want to -delete
tego, czego nie zrobiłeś na praktycznym przykładzie?
-n
opcji -delete ; Oczywiście pierwsze polecenie nie powinno mieć żadnego praktycznego zastosowania; Pójdę to zmienić.
Bardzo find
ważna jest kolejność argumentów.
Argumentami mogą być opcje, testy i akcje. Zazwyczaj powinieneś najpierw użyć opcji, potem testów, a następnie akcji.
Czasami find
nawet ostrzega cię przed możliwym złym uporządkowaniem (na przykład, gdy używasz -maxdepth
innych argumentów), ale innym wydaje się, że tak nie jest.
Co find . -delete -name '*ar'
to jest:
Prawdopodobnie chcesz to zrobić:
find -name '*ar' -delete
Spowoduje to, dla każdego pliku, czy pasuje '*ar'
, i tylko jeśli spełni warunek, usunie plik.
Przepraszam, jeśli dowiedziałeś się za późno.