Är det möjligt att använda två kommandon i -exec delen av find kommando?

Jag har provat något som:

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

och jag får:

hitta: saknar argument till -exec
chmod: kan inte komma åt {}: Ingen sådan fil eller katalog
chmod: kan inte komma åt;: Ingen sådan fil eller katalog

Kommentarer

  • Observera att -name "*" matchar alla namn, så det är ' ett no-op-test som kan tas bort. Både chmod och chgrp har ett -R -alternativ för rekursiv operation.

Svar

När det gäller kommandot find kan du bara lägga till fler -exec kommandon i rad:

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

Observera att det här kommandot är i sitt resultat t, motsvarande att använda

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

i varje fil.

Alla find ”-parametrar som -name, -exec, -size och så vidare är faktiskt test : find kommer att fortsätta köra dem en efter en så länge hela kedjan hittills har utvärderats till true . Så varje kommande -exec -kommando körs endast om de föregående returnerade true (dvs. 0 kommandona avsluta status). Men find förstår också logikoperatorer som eller (-o) och inte (!). Därför att använda en kedja av -exec testar oavsett av föregående resultat, man skulle behöva använda något så här:

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

Kommentarer

  • +1: Ja, det ' är det mest eleganta sättet att göra det. Om du kan förklara varför du använder '{}' (apostrof runt hängslen), besök: unix.stackexchange.com/q/ 8647/4485
  • @user Tyvärr vet jag inte ' om det fortfarande är nödvändigt. Jag testade just nu och har inte ' inte stött på en situation där det skulle ändra någonting. Jag antar att det ' är bara " god praxis " som kommer att dö ut.
  • Citaten är viktiga för filer med mellanslag i deras namn.
  • @ naught101 Nej, citaten kan behövas i vissa icke-standardiserade skal, till exempel fish och csh, men behövs definitivt inte i POSIX-liknande skal (sh, dash, bash, zsh, ksh, yash).

Svar

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

Kommentarer

  • @Gilles: Underet av -c ' s udda hantering på $ 0 får mig att tro att det här är fel varje gång jag tittar på det, men det är definitivt korrekt.
  • Jag gillar att det explicita skalet definieras …
  • Detta svar (och Giles ' är en svara) verkar som det bättre svaret på frågan med tanke på sh -c.

Svar

Ditt kommando analyseras först av skalet i två kommandon åtskilda av en ;, vilket motsvarar en ny rad:

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

Om du vill köra ett skalkommando, anropa ett skal uttryckligen med bash -c (eller sh -c om du bryr dig inte om att skalet är specifikt bash):

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

Observera att {} används argument till skalet; det är nollargumentet (som normalt är namnet på skalet eller skriptet, men detta spelar ingen roll här), och hänvisas därför till "$0".

Du kan skicka flera filnamn till skalet åt gången och göra skalet itera igenom dem, det kommer att vara snabbare. Här skickar jag _ som manusnamn och följande argument är filnamn, som for x (en genväg för for x in "$@") itererar över.

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

Observera att eftersom bash 4, eller i zsh, inte behöver hitta alls här. I bash, kör shopt -s globstar (lägg det i din ~/.bashrc) för att aktivera **/ som står för en rekursiv katalogglob. (I zsh är detta aktiv hela tiden.) Då

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

eller om du vill att filerna ska upprepas i ordning

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

En skillnad med kommandot find är att skalet ignorerar punktfiler (filer vars namn börjar med . För att inkludera dem, i bash, ställ först in GLOBIGNORE=.:..; i zsh, använd **/*(D) som globmönster.

Kommentarer

  • Detta svar (och Glenn ' s svar) verkar vara det bättre svaret på frågan med tanke på sh -c.
  • Både chgrp och chmod har en -R alternativ för rekursiv operation.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *