Czy można użyć 2 poleceń w -exec części find polecenie?

Próbowałem czegoś takiego:

find . -name "*" -exec chgrp -v new_group {} ; chmod -v 770 {} \; 

i otrzymałem:

find: brak argumentu -exec
chmod: brak dostępu {}: brak takiego pliku lub katalogu
chmod: brak dostępu;: brak takiego pliku lub katalogu

Komentarze

  • Pamiętaj, że -name "*" pasuje do każdego nazwiska, więc ' jest testem bez operacji, który można usunąć. Ponadto zarówno chmod, jak i chgrp ma opcję -R do operacji rekurencyjnej.

Odpowiedź

Jeśli chodzi o polecenie find, możesz także dodać więcej -exec poleceń z rzędu:

find . -name "*" -exec chgrp -v new_group "{}" \; -exec chmod -v 770 "{}" \; 

Zauważ, że to polecenie jest w swoim resul t, odpowiednik użycia

chgrp -v new_group file & & plik chmod -v 770

w każdym pliku.

Wszystkie parametry find „, takie jak -name, -exec, -size i tak dalej, są w rzeczywistości testami : find będzie je uruchamiać jeden po drugim, o ile cały dotychczasowy łańcuch uzyskał wartość true . Zatem każde kolejne polecenie -exec jest wykonywane tylko wtedy, gdy poprzednie zwróciły true (tj. 0 status wyjścia poleceń). Ale find rozumie również operatory logiczne, takie jak lub (-o), a nie (!). Dlatego, aby użyć łańcucha -exec testów niezależnie od poprzednich wyników, należałoby użyć czegoś takiego:

find . -name "*" \( -exec chgrp -v new_group {} \; -o -true \) -exec chmod -v 770 {} \; 

Komentarze

  • +1: Tak, to ' to najbardziej elegancki sposób na zrobienie tego. Jeśli możesz wyjaśnić, dlaczego używasz '{}' (apostrofy w nawiasach), odwiedź: unix.stackexchange.com/q/ 8647/4485
  • @user Niestety, nie ' nie wiem, czy jest to nadal konieczne. Przeprowadziłem przed chwilą jakiś test i nie ' nie znalazłem sytuacji, w której mogłoby to coś zmienić. Myślę, że ' to tylko " dobra praktyka ", która wymrze.
  • Cudzysłowy są ważne w przypadku plików ze spacjami w nazwach.
  • @ naught101 Nie, cudzysłowy mogą być potrzebne w niektórych niestandardowych powłokach, takich jak fish i csh, ale zdecydowanie nie są potrzebne w powłokach podobnych do POSIX (sh, dash, bash, zsh, ksh, yash).

Odpowiedź

find . -name "*" -exec sh -c "chgrp -v new_group "$0" ; chmod -v 770 "$0"" {} \; 

Komentarze

  • @Gilles: Cuda z -c ' dziwna obsługa z $ 0 sprawia, że myślę, że to źle za każdym razem, gdy na to spojrzę, ale jest zdecydowanie poprawne.
  • Podoba mi się definiowanie jawnej powłoki …
  • Ta odpowiedź (i Giles ' s an swer) wydaje się lepszą odpowiedzią na pytanie, biorąc pod uwagę sh -c.

Odpowiedź

Twoje polecenie jest najpierw analizowane przez powłokę na dwa polecenia oddzielone znakiem ;, co odpowiada nowej linii:

find . -name "*" -exec chgrp -v new_group {} chmod -v 770 {} \; 

Jeśli chcesz uruchomić polecenie powłoki, wywołaj powłokę jawnie za pomocą bash -c (lub sh -c jeśli nie obchodzi cię, że powłoka jest specjalnie bash):

find . -name "*" -exec sh -c "chgrp -v new_group "$0"; chmod -v 770 "$0"" {} \; 

Zwróć uwagę na użycie {} jako argument do powłoki; jest to argument zerowy (zwykle jest to nazwa powłoki lub skryptu, ale nie ma to znaczenia w tym przypadku), stąd odniesienie to "$0".

Możesz przekazać wiele nazw plików naraz i sprawić, by powłoka przeszła przez nie, będzie to szybsze. Tutaj przekazuję _ jako nazwę skryptu i następujące argumenty są nazwy plików, które for x (skrót do for x in "$@") są powtarzane.

find . -name "*" -exec sh -c "for x; do chgrp -v new_group "$x"; chmod -v 770 "$x"; done" _ {} + 

Zauważ, że od bash 4, czyli zsh, nie musisz tutaj w ogóle szukać. W bash, uruchom shopt -s globstar (umieść go w swoim ~/.bashrc), aby aktywować **/ jako katalog rekurencyjny glob. (w zsh jest to cały czas aktywny). Następnie

chgrp -v new_group -- **/*; chmod -v 770 -- **/* 

lub jeśli chcesz, aby pliki były iterowane w kolejności

for x in **/*; do chgrp -v new_group -- "$x" chmod -v 770 -- "$x" done 

Jedną z różnic w stosunku do polecenia find jest to, że powłoka ignoruje pliki z kropkami (pliki, których nazwa zaczyna się od . ). Aby je uwzględnić, w bash najpierw ustaw GLOBIGNORE=.:..; w zsh użyj **/*(D) jako wzorca glob.

Komentarze

  • Ta odpowiedź (i odpowiedź Glenna ') wydaje się być lepszą odpowiedzią na pytanie podane sh -c.
  • Zarówno chgrp, jak i chmod mają -R dla operacji rekurencyjnej.

Dodaj komentarz

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