Er det mulig å bruke to kommandoer i -exec delen av find kommando?

Jeg har prøvd noe sånt som:

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

og jeg får:

finn: mangler argument til -exec
chmod: får ikke tilgang {}: Ingen slik fil eller katalog
chmod: får ikke tilgang ;: Ingen slik fil eller katalog

Kommentarer

  • Merk at -name "*" samsvarer med hvert navn, så det ' er en no-op test som kan fjernes. Også både chmod og chgrp har et -R alternativ for rekursiv operasjon.

Svar

Når det gjelder find kommandoen, kan du også bare legge til flere -exec kommandoer på rad:

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

Merk at denne kommandoen er i sin resultat t, tilsvarer bruk av

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

på hver fil.

Alle find «s parametere som -name, -exec, -size og så videre, er faktisk tester : find vil fortsette å kjøre dem en etter en så lenge hele kjeden så langt har evaluert til true . Så hver påfølgende -exec -kommando utføres bare hvis de forrige returnerte true (dvs. 0 exit kommandoer). Men find forstår også logiske operatorer som eller (-o) og ikke (!). Derfor, for å bruke en kjede av -exec tester uansett av de forrige resultatene, man trenger å bruke noe slikt:

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

Kommentarer

  • +1: Ja, det ' er den mest elegante måten å gjøre det på. Hvis du kan forklare hvorfor du bruker '{}' (apostrofer rundt klammeparentesene), kan du gå til: unix.stackexchange.com/q/ 8647/4485
  • @user Dessverre vet jeg ikke ' om det fortsatt er nødvendig. Jeg testet akkurat nå og har ikke ' ikke kommet over en situasjon der det ville endre noe. Jeg antar at det ' er bare " god praksis " som vil dø ut.
  • Sitatene er viktige for filer med mellomrom i navnene.
  • @ naught101 Nei, anførselstegnene kan være nødvendige i noen ikke-standardiserte skall, for eksempel fish og csh, men er absolutt ikke nødvendig i POSIX-lignende skjell (sh, dash, bash, zsh, ksh, yash).

Svar

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

Kommentarer

  • @Gilles: Underverkene til -c ' s rare håndtering på $ 0 får meg til å tro at dette er galt hver gang jeg ser på det, men det er definitivt riktig.
  • Jeg liker at det eksplisitte skallet blir definert …
  • Dette svaret (og Giles ' er en svare) virker som det bedre svaret på spørsmålet gitt sh -c.

Svar

Kommandoen din blir først analysert av skallet i to kommandoer atskilt med en ;, som tilsvarer en ny linje:

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

Hvis du vil kjøre en shell-kommando, kan du påkalle et skall eksplisitt med bash -c (eller sh -c hvis du bryr deg ikke om at skallet er spesifikt bash):

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

Legg merke til bruken av {} argument til skallet; det er nullverdige argumentet (som vanligvis er navnet på skallet eller skriptet, men dette betyr ikke noe her), derav referert til som "$0".

Du kan sende flere filnavn til skallet om gangen og få skallet til å gjentas gjennom dem, det vil være raskere. Her sender jeg _ som manusnavnet og følgende argumenter er filnavn, som for x (en snarvei for for x in "$@") gjentas over.

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

Merk at siden bash 4, eller i zsh, trenger du ikke å finne noe her. I bash, kjør shopt -s globstar (legg det i ~/.bashrc) for å aktivere **/ som står for en rekursiv katalog glob. (I zsh er dette aktiv hele tiden.) Så

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

eller hvis du vil at filene skal gjentas på i rekkefølge

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

En forskjell med find kommandoen er at skallet ignorerer punktfiler (filer hvis navn begynner med en . For å inkludere dem, i bash, sett først GLOBIGNORE=.:..; i zsh, bruk **/*(D) som globmønsteret.

Kommentarer

  • Dette svaret (og Glenn ' s svar) virker som det bedre svaret på spørsmålet gitt sh -c.
  • Både chgrp og chmod har en -R alternativ for rekursiv drift.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *