Próbuję uruchomić następujące polecenie:
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar "{}" +
To zwraca błąd:
find: missing argument to -exec
Nie mogę zobaczyć, co jest nie tak z tym poleceniem, ponieważ wygląda na to, że pasuje do strony podręcznika :
-exec polecenie {} +
Ten wariant opcji -exec uruchamia określone polecenie na wybranych plikach, ale linia poleceń jest budowana przez dołączenie nazwy każdego wybranego pliku na końcu; całkowita liczba wywołań polecenia będzie znacznie mniejsza niż liczba dopasowanych plików. Linia poleceń jest zbudowana w podobny sposób, w jaki xargs buduje swoje wiersze poleceń. W poleceniu dozwolone jest tylko jedno wystąpienie „{}”. Polecenie jest wykonywane w katalogu początkowym.
Próbowałem też:
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar {} + find a/folder b/folder -name *.c -o -name *.h -exec "grep -I foobar" {} + find a/folder b/folder -name *.c -o -name *.h -exec "grep -I foobar" "{}" + find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar "{}" + find a/folder b/folder \( -name *.c -o -name *.h \) -exec grep -I foobar "{}" + find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar "{}" \+
Komentarze
Odpowiedź
Była kilka problemów z twoimi próbami, w tym cudzysłowy używane zamiast cudzysłowów (usunięte w późniejszych edycjach pytania), brakujące cudzysłowy tam, gdzie są wymagane, dodatkowe cudzysłowy, gdy są bezużyteczne, brakujące nawiasy w grupie -o
i różne implementacje find
użyte (szczegóły w komentarzach i czacie).
W każdym razie polecenie można uprościć w ten sposób:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +
lub, jeśli używasz archaicznej wersji GNU find, powinno to zawsze działać:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;
Komentarze
- Ups, miały być cudzysłowami, a nie znakami odwrotnymi.
- Cytaty byłyby bezużyteczne, ponieważ
{}
nie ma określonego znaczenia dla powłoki. - Ze stron podręcznika Find: ” Ciąg ' { } ' jest zastąpiona bieżącą nazwą przetwarzanego pliku wszędzie tam, gdzie występuje w argumentach polecenia, a nie tylko w argumentach, w których występuje samodzielnie, jak w niektórych wersjach find. Obie te konstrukcje mogą wymagać zmiany znaczenia (z ' \ ') lub zacytowania, aby chronić je przed rozwinięciem przez powłokę. ”
- Rzeczywiście przeczytałem to na stronie podręcznika, ale faktem jest, że nie ma powłoki, ' jestem tego świadomy to wymaga cytowania nawiasów klamrowych. Jakiej powłoki używasz?
- bash. Z cudzysłowami lub bez nich i tak otrzymuję błąd.
Odpowiedź
“brakujący argument do ”zwykle oznacza, że w argumencie – exec
brakuje terminatora. Terminator musi być argumentem zawierającym tylko znak ;
(który musi być cytowany w poleceniu powłoki, więc zwykle jest zapisywany \;
lub ";"
) albo dwa kolejne argumenty zawierające {}
i +
.
Stephane Chazelas stwierdził , że „używasz starszej wersji narzędzia GNU find, która nie obsługuje -exec … {} +
, tylko -exec {} \;
.Chociaż GNU późno zaadoptował -exec … {} +
, polecam zakup mniej starodawnego zestawu narzędzi (takiego jak Cygwin , który zawiera git i dużo więcej, lub GNUwin32 , w którym brakuje gita, ale nie ma on „złego pracownika-próbującego-użyć-linuxa” -ale-my-impose-windows vibe, który daje Cygwin). Ta funkcja została dodana w wersji 4.2.12 ponad 9 lat temu (była to ostatnia zidentyfikowana funkcja, która sprawiła, że GNU find
Zgodny z POSIX).
Jeśli chcesz trzymać się starszego znaleziska GNU, możesz użyć -print0
z xargs -0
aby uzyskać podobną funkcjonalność: zgrupowane wykonywanie poleceń, obsługa dowolnych nazw plików.
find a/folder b/folder -name "*.c" -o -name "*.h" -print0 | xargs -0 grep -I foobar /dev/null
Zawsze cytuj symbole wieloznaczne w find
. W przeciwnym razie, jeśli zdarzy się, że uruchomisz to polecenie z katalogu zawierającego pliki .c
, *.c
bez cudzysłowu d należy rozwinąć do listy plików .c
w bieżącym katalogu.
Dodanie /dev/null
do grep
to sztuczka, dzięki której grep zawsze wypisze nazwę pliku, nawet jeśli find
znajdzie jedno dopasowanie. W przypadku wyszukiwania GNU inną metodą jest przekazanie opcji -H
.
Komentarze
- Co robisz znaczy przez zły-pracownik-próbujący-użyć-linux-ale-na-nakładamy-windowsowy klimat, który daje cygwin?
- GNUwin32 nie ' nie spodziewałem się 🙁
- Zobacz mój komentarz (y) do pytania.
- Cytaty wokół półproduktu pracowały z poziomu skryptu package.json.
Odpowiedź
Jeśli polecenie takie jak
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +
zwróci błąd
find: missing argument to -exec
prawdopodobną przyczyną jest zbyt stary GNU find
, który nie obsługuje składni -exec mycommand {} +
. W takim przypadku zamiennik o niskiej wydajności polega na uruchomieniu -exec mycommand {} \;
, co spowoduje uruchomienie mycommand
raz dla każdego znalezionego celu zamiast zbierania wielu celów i uruchamiając mycommand
tylko raz.
Jednak GNU find
doe nie obsługuje np.
find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +
ponieważ GNU find
obsługuje tylko kombinację literałów {} +
zamiast bardziej ogólnego {} additional parameters +
. Zwróć uwagę, że między nawiasami klamrowymi a znakiem +
nie może znajdować się nic. Jeśli spróbujesz tego, pojawi się ten sam błąd:
find: missing argument to -exec
Obejście polega na zastosowaniu składni {} additional parameters \;
, która działa, ale wykona polecenie raz dla każdego znalezionego celu. Jeśli potrzebujesz większej wydajności z GNU find
, musisz napisać skrypt opakowujący, który może dołączyć dodatkowe parametry do podanych argumentów. Coś w rodzaju
#!/bin/bash exec mycommand "$@" additional parameters
powinno wystarczyć. Lub, jeśli nie chcesz tworzyć pliku tymczasowego, możesz użyć jednej linii, aby zmienić kolejność parametrów w następujący sposób:
find . -type f -and -name "*.ttf" -exec bash -c "mycommand "$@" extra arguments" {} +
, który wykona mycommand {list of ttf files} extra arguments
. Pamiętaj, że może być konieczne podwójne wprowadzenie zmiany znaczenia dla znaków specjalnych dla bash po fladze -c
.
Komentarze
- (1) Część powyższego, która faktycznie odpowiada na pytanie, została już podana przez inne osoby. (2) To, co opisujesz, nie jest wadą lub brakiem w GNU
find
, ale poprawnym zachowaniem określonym przez POSIX . - +1 Wreszcie ktoś, kto odpowie, dlaczego dodatkowe parametry nie ' nie działają! Wygląda na to, że brakuje definicji POSIX.
- Jeśli ' ve GNU
find
to ' prawdopodobnie masz GNUcp
. W takim przypadku możeszfind ... -exec cp --target-directory ~/.fonts {} +
zachować{}
na końcu ciągu wykonywania.
Odpowiedź
find . -type f -perm 0777 -exec chmod 644 {}\;
napotkał błąd find: missing argument to ``-exec"
.
Dodanie spacji między {}
a \
naprawiono:
find . -type f -perm 0777 -print -exec chmod 644 {} \;
Komentarze
- Nie ma takiego problemu w
find
w zadanym pytaniu. - W pytaniu nie jest dobrze, że zrozumiałem, ale problem jest ten sam ” find: missing argument na „ -exec ' „, Problem może wystąpić z innego-2 powodu. Odpowiedziałem, ponieważ widziałem to samo stwierdzenie problemu.
- @Kusalananda, dobry żal, noob zapewnił rozwiązanie zgłoszonego błędu, które zostało określone przez OP zarówno w tytule, jak i treści pytania.
- @bvj Pytanie wyraźnie dotyczy z
+
formularzem opcji-exec
nafind
. Ta odpowiedź rozwiązuje problem, którego nie ma użytkownik zadający pytanie.
Odpowiedź
Mój udział bólów głowy ze składnią exec w przeszłości. przez większość dni wolę ładniejszą składnię basha:
for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done
Ma pewne ograniczenia, gdy chcesz traktować pliki jako grupę, ponieważ każdy jest oceniany kolejno, ale możesz potokować wyjście w innym miejscu.
Komentarze
- Chociaż to zwykle działa, jest znacznie mniej użyteczne niż wersja z funkcją wyszukiwania, ponieważ nie może poprawnie obsługiwać plików z białymi znakami w nazwie.
- Nie, ' nie rób tego. Dzieje się tak, gdy tylko pliki zawierają spacje i inne „dziwne” znaki. Jest to również bardziej złożone i wolniejsze niż
find … -exec … \;
, więc ' nie ma powodu, aby go używać, nawet jeśli wiesz, że nazwy plików są tame. - było to pomocne w mojej sytuacji, w której musiałem uruchomić wiele linii logiki w oparciu o nazwy plików (np. usuwanie znaków, tworzenie katalogów, a następnie przenoszenie plików). Próbowanie znalezienia możliwości zrobienia wielu rzeczy w jednym
exec
było zbyt dużym bólem głowy przez 5 minut, które chciałem na to poświęcić. Moje nazwy plików były oswojone i to rozwiązało mój problem 🙂
+
na koniec?find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
find
. Chociaż wariant-exec cmd {} +
jest zgodny z POSIX i był dostępny od lat 80-tych, GNU find dodał go dopiero (stosunkowo) niedawno (2005). Co mówifind --version
?-exec {} +
zostało dodane w 4.2.12 w 2005 r. W starszych znaleziskach GNU możesz użyć (nie-POSIX)-print0 | xargs -r0
, aby coś uzyskać podobny.4.1
pochodzi z 1994 roku.-name
argumenty należy cytować:-name "*.c" -o -name "*.h"
. To prawda, chociaż nie ma to związku z błędem-exec
. Zauważysz, że wszystkie inne odpowiedzi umieszczają symbole wieloznaczne w cudzysłowie, chociaż wspomina o tym tylko Gilles. … (Ciąg dalszy)-name "*.[ch]"
bez wyjaśnienia. Ma to tę zaletę, że upraszcza wiersz poleceń, a konkretnie eliminuje-o
. Znalezienie wyrażeń obejmujących-o
jest trudne do ustalenia. Twój jest zły; jeśli polecenie zostało naprawione i nie zawiera błędu (jak w odpowiedzi Gillesa), będzie ono działaćgrep
tylko na.h
akta. Musisz wykonać'(' -name '*.c' -o -name '*.h' ')'
.