-exec
Komenda musi zostać zakończona ;
(tak zwykle trzeba wpisać \;
lub ';'
w celu uniknięcia interpretion przez powłokę) lub +
. Różnica polega na tym ;
, że z , polecenie jest wywoływane raz na plik, z +
, jest wywoływane tak mało razy, jak to możliwe (zwykle raz, ale linia poleceń ma maksymalną długość, więc można ją podzielić) ze wszystkimi nazwami plików . Zobacz ten przykład:
$ cat /tmp/echoargs
#!/bin/sh
echo $1 - $2 - $3
$ find /tmp/foo -exec /tmp/echoargs {} \;
/tmp/foo - -
/tmp/foo/one - -
/tmp/foo/two - -
$ find /tmp/foo -exec /tmp/echoargs {} +
/tmp/foo - /tmp/foo/one - /tmp/foo/two
Twoje polecenie ma dwa błędy:
Po pierwsze, używasz {};
, ale ;
musi być własnym parametrem.
Po drugie, polecenie kończy się na &&
. Podałeś „uruchom find, a jeśli to się powiedzie, usuń plik o nazwie {};
.”. Jeśli chcesz użyć powłoki w -exec
poleceniu, musisz jawnie uruchomić ją w powłoce, takiej jak -exec sh -c 'ffmpeg ... && rm'
.
Jednak nie należy dodawać {} wewnątrz polecenia bash, spowoduje to problemy, gdy będą znaki specjalne. Zamiast tego możesz przekazać dodatkowe parametry do powłoki po -c command_string
(patrz man sh
):
$ ls
$(echo damn.)
$ find * -exec sh -c 'echo "{}"' \;
damn.
$ find * -exec sh -c 'echo "$1"' - {} \;
$(echo damn.)
Widzisz, że $
rzecz jest oceniana przez powłokę w pierwszym przykładzie. Wyobraź sobie, że istnieje plik o nazwie $(rm -rf /)
:-)
(Uwaga dodatkowa: Nie -
jest potrzebna, ale pierwsza zmienna po poleceniu jest przypisana do zmiennej $0
, która jest specjalną zmienną zwykle zawierającą nazwę uruchamianego programu i ustawienie tego parametru na parametr jest trochę nieczyste, chociaż wygrało prawdopodobnie nie zaszkodzi tutaj, więc ustawiliśmy to na -
początek i zaczynamy od $1
).
Więc twoje polecenie może być podobne
find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \;
Ale jest lepszy sposób. znajdź wsparcie and
i or
, więc możesz robić rzeczy takie jak find -name foo -or -name bar
. Ale to również działa z -exec
, co daje wartość true, jeśli polecenie zakończy się pomyślnie, i false, jeśli nie. Zobacz ten przykład:
$ ls
false true
$ find * -exec {} \; -and -print
true
Uruchamia druk tylko wtedy, gdy polecenie zakończyło się powodzeniem, true
ale nie dla false
.
Możesz więc użyć dwóch instrukcji exec połączonych łańcuchem z -and
, i wykona to drugie, tylko jeśli pierwsza zostanie pomyślnie uruchomiona.