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.
findOpcja -deletejest 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 findzrobi polecenie:
Aby zobaczyć, jak lubi polecenie
find . -name '*ar' -delete
usunie, możesz najpierw zastąpić akcję -deletebardziej nieszkodliwym działaniem - takim jak -flslub -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)
-deleteflagę :-) Ale czy istnieje jakiś powód, by ktoś kiedykolwiek zrobić find . -deletezamiast rm -rf .? A może tak właśnie się dzieje, gdy findanalizuje i przetwarza swoje argumenty?
warning: use -depth when testing stuff you later want to -deletetego, czego nie zrobiłeś na praktycznym przykładzie?
-nopcji -delete ; Oczywiście pierwsze polecenie nie powinno mieć żadnego praktycznego zastosowania; Pójdę to zmienić.
Bardzo findważ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 findnawet ostrzega cię przed możliwym złym uporządkowaniem (na przykład, gdy używasz -maxdepthinnych 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.