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

  • Czy próbowałeś zmienić znaczenie + na koniec? find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
  • Być może używasz starej wersji GNU 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ówi find --version?
  • @Koveras, to by było na tyle. -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.
  • JRFerguson wskazał (w odpowiedzi, która została usunięta), że wzorzec -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)
  • (ciąg dalszy)… Odpowiedź jlliagre zwija wyrażenie nazwy do -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' ')'.

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 GNU cp. W takim przypadku możesz find ... -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 na find. 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 🙂

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *