È possibile utilizzare 2 comandi nella -exec parte di find comando?

Ho provato qualcosa del tipo:

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

e ottengo:

find: argomento mancante per -exec
chmod: impossibile accedere {}: nessun file o directory di questo tipo
chmod: impossibile accedere;: nessun file o directory di questo tipo

Commenti

  • Tieni presente che -name "*" corrisponde a ogni nome, quindi è ' un test non operativo che può essere rimosso. Inoltre, sia chmod che chgrp ha unopzione -R per loperazione ricorsiva.

Risposta

Per quanto riguarda il comando find, puoi anche aggiungere altri -exec comandi di seguito:

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

Nota che questo comando è, nel suo risultato t, equivalente allutilizzo di

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

su ogni file.

Tutti i find “parametri come -name, -exec, -size e così via, sono in realtà test : find continuerà a eseguirli uno per uno fino a quando lintera catena è stata valutata come true . Quindi ogni comando -exec consecutivo viene eseguito solo se i precedenti hanno restituito true (cioè 0 stato di uscita dei comandi). Ma find comprende anche operatori logici come o (-o) e non (!). Pertanto, per utilizzare una catena di -exec test indipendentemente dei risultati precedenti, si dovrebbe usare qualcosa del genere:

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

Commenti

  • +1: Sì, quello ' è il modo più elegante per farlo. Se puoi spiegare il motivo per cui utilizzi '{}' (apostrofi attorno alle parentesi graffe), visita: unix.stackexchange.com/q/ 8647/4485
  • @user Sfortunatamente, non ' non so se è ancora necessario. Ho fatto qualche prova proprio ora e non ' mi sono imbattuto in una situazione in cui cambierebbe qualcosa. Immagino che ' sia solo " buona pratica " che si estinguerà.
  • Le virgolette sono importanti per i file con spazi nei nomi.
  • @ naught101 No, le virgolette potrebbero essere necessarie in alcune shell non standard, come fish e csh, ma sicuramente non sono necessari nelle shell simili a POSIX (sh, dash, bash, zsh, ksh, yash).

Risposta

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

Commenti

  • @Gilles: The wonders of -c ' s strana gestione di $ 0 mi fa pensare che sia sbagliato ogni volta che la guardo, ma è decisamente corretto.
  • Mi piace che la shell esplicita sia definita …
  • Questa risposta (e Giles ' è un swer) sembra la risposta migliore per la domanda data la sh -c.

Risposta

Il tuo comando viene prima analizzato dalla shell in due comandi separati da un ;, che è equivalente a una nuova riga:

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

Se desideri eseguire un comando di shell, invoca esplicitamente una shell con bash -c (o sh -c se non ti interessa che la shell sia specificamente bash):

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

Nota luso di {} come argomento alla shell; è largomento zero (che normalmente è il nome della shell o dello script, ma qui non ha importanza), quindi indicato come "$0".

Puoi passare più nomi di file alla shell alla volta e far scorrere la shell attraverso di essi, “sarà più veloce. Qui passo _ come nome dello script e i seguenti argomenti sono nomi di file, su cui for x (una scorciatoia per for x in "$@") viene ripetuto.

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

Nota che da bash 4, o in zsh, non è necessario trovarlo qui. In bash, esegui shopt -s globstar (inseriscilo nel tuo ~/.bashrc) per attivare **/ che sta per una directory glob ricorsiva (in zsh, questo è sempre attivo.) Quindi

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

o se desideri che i file vengano ripetuti in ordine

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

Una differenza con il comando find è che la shell ignora i file punto (file il cui nome inizia con . ). Per includerli, in bash, imposta prima GLOBIGNORE=.:..; in zsh, utilizza **/*(D) come modello glob.

Commenti

  • Questa risposta (e la risposta di Glenn ') sembra la migliore risposta alla domanda data la sh -c.
  • Sia chgrp che chmod hanno un -R opzione per operazioni ricorsive.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *