Is het mogelijk om 2 commandos te gebruiken in het -exec
deel van find
commando?
Ik heb zoiets geprobeerd als:
find . -name "*" -exec chgrp -v new_group {} ; chmod -v 770 {} \;
en ik krijg:
zoek: ontbrekend argument voor -exec
chmod: kan geen toegang krijgen {}: bestand of map bestaat niet
chmod: kan geen toegang krijgen;: bestand of map bestaat niet
Reacties
Answer
Wat betreft het find
commando, je kunt ook gewoon meer -exec
commandos achter elkaar toevoegen:
find . -name "*" -exec chgrp -v new_group "{}" \; -exec chmod -v 770 "{}" \;
Merk op dat dit commando het resultaat is t, equivalent van het gebruik van
chgrp -v new_group file & & chmod -v 770 bestand
op elk bestand.
Alle find
“s parameters zoals -name
, -exec
, -size
enzovoort, zijn eigenlijk tests : find
zal ze een voor een blijven uitvoeren zolang de hele keten tot dusver is geëvalueerd als true . Dus elke opeenvolgende -exec
-opdracht wordt alleen uitgevoerd als de vorige 0
exit-status van de commandos). Maar find
begrijpt ook logische operatoren zoals of (-o
) en niet (!
). Om daarom een ketting van -exec
tests te gebruiken ongeacht van de vorige resultaten, je zou zoiets als dit moeten gebruiken:
find . -name "*" \( -exec chgrp -v new_group {} \; -o -true \) -exec chmod -v 770 {} \;
Reacties
- +1: Ja, dat ' is de meest elegante manier om het te doen. Als je kunt uitleggen waarom je
'{}'
(apostrofs rond de accolades) gebruikt, ga dan naar: unix.stackexchange.com/q/ 8647/4485 - @user Helaas weet ik niet ' of het nog steeds nodig is. Ik heb zojuist een test gedaan en ben ' niet een situatie tegengekomen waarin het iets zou veranderen. Ik denk dat het ' slechts " goede praktijk " is die zal verdwijnen.
- De aanhalingstekens zijn belangrijk voor bestanden met spaties in hun naam.
- @ naught101 Nee, de aanhalingstekens kunnen nodig zijn in sommige niet-standaard shells, zoals
fish
encsh
, maar zijn zeker niet nodig in POSIX-achtige shells (sh
,dash
,bash
,zsh
,ksh
,yash
).
Antwoord
find . -name "*" -exec sh -c "chgrp -v new_group "$0" ; chmod -v 770 "$0"" {} \;
Reacties
- @Gilles: The wonders of
-c
' s vreemde afhandeling van $ 0 doen me denken dat dit elke keer als ik ernaar kijk verkeerd is, maar het is absoluut correct. - Ik vind de expliciete shell die wordt gedefinieerd leuk …
- Dit antwoord (en Giles ' is een swer) lijkt het betere antwoord op de vraag gezien de
sh -c
.
Antwoord
Uw commando wordt eerst door de shell geparseerd in twee commandos gescheiden door een ;
, wat gelijk is aan een nieuwe regel:
find . -name "*" -exec chgrp -v new_group {} chmod -v 770 {} \;
Als je een shell-commando wilt uitvoeren, roep dan expliciet een shell aan met bash -c
(of sh -c
als het kan je niet schelen dat de shell specifiek bash is):
find . -name "*" -exec sh -c "chgrp -v new_group "$0"; chmod -v 770 "$0"" {} \;
Let op het gebruik van {}
als een argument tegen de schaal; het is het nulde argument (wat normaal de naam is van de shell of het script, maar dit maakt hier niet uit), daarom wordt er naar verwezen als "$0"
.
Je kunt meerdere bestandsnamen tegelijk aan de shell doorgeven en de shell er doorheen laten herhalen, het “zal sneller zijn. Hier geef ik _
door als de scriptnaam en de volgende argumenten zijn bestandsnamen, die for x
(een snelkoppeling voor for x in "$@"
) herhalen.
find . -name "*" -exec sh -c "for x; do chgrp -v new_group "$x"; chmod -v 770 "$x"; done" _ {} +
Merk op dat sinds bash 4, of in zsh, je hier helemaal niets hoeft te vinden. Voer in bash (plaats het in uw ~/.bashrc
) om **/
te activeren die staat voor een recursieve directory glob. (In zsh is dit de hele tijd actief.) Dan
chgrp -v new_group -- **/*; chmod -v 770 -- **/*
of als je wilt dat de bestanden op volgorde worden herhaald
for x in **/*; do chgrp -v new_group -- "$x" chmod -v 770 -- "$x" done
Een verschil met het find
commando is dat de shell puntbestanden negeert (bestanden waarvan de naam begint met een .
). Om ze in bash op te nemen, stelt u eerst GLOBIGNORE=.:..
in; in zsh gebruikt u **/*(D)
als het glob-patroon.
Reacties
- Dit antwoord (en Glenn ' s antwoord) lijkt het betere antwoord op de vraag gezien de
sh -c
. - Zowel
chgrp
alschmod
hebben een-R
optie voor recursieve bewerking.
-name "*"
overeenkomt met elke naam, dus het ' is een no-op-test die kan worden verwijderd. Bovendien zijn zowelchmod
alschgrp
heeft een-R
optie voor recursieve bewerking.