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
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
icsh
, 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 ichmod
mają-R
dla operacji rekurencyjnej.
-name "*"
pasuje do każdego nazwiska, więc ' jest testem bez operacji, który można usunąć. Ponadto zarównochmod
, jak ichgrp
ma opcję-R
do operacji rekurencyjnej.