Je možné použít 2 příkazy v -exec části find příkaz?

Zkusil jsem něco jako:

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

a dostanu:

najít: chybějící argument pro -exec
chmod: nelze získat přístup {}: Žádný takový soubor nebo adresář
chmod: nelze získat přístup:: Žádný takový soubor nebo adresář

Komentáře

  • Upozorňujeme, že -name "*" odpovídá každému jménu, takže je ' sa no-op test, který lze odstranit. Také chmod a chgrp-R možnost rekurzivního provozu.

odpověď

Pokud jde o příkaz find, můžete také přidat další -exec příkazy za sebou:

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

Všimněte si, že tento příkaz je ve svém výsledku t, ekvivalent použití

chgrp -v new_group soubor & & chmod -v 770 soubor

na každém souboru.

Všechny find parametry, jako je -name, -exec, -size atd. jsou ve skutečnosti testy : find je bude nadále spouštět jeden po druhém, pokud je dosud celý řetězec vyhodnocen jako true . Takže každý následující -exec příkaz je proveden pouze v případě, že předchozí vrátili true (tj. 0 stav ukončení příkazů). Ale find rozumí také logickým operátorům jako nebo (-o) a ne (!). Proto použít řetězec -exec testů bez ohledu na předchozích výsledků, člověk by musel použít něco takového:

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

Komentáře

  • +1: Ano, to ' je nejelegantnější způsob, jak to udělat. Pokud můžete vysvětlit, proč používáte '{}' (apostrofy ve složených závorkách), navštivte: unix.stackexchange.com/q/ 8647/4485
  • @user Bohužel nevím ' zda je to stále nutné. Právě jsem provedl nějaký test a nenarazil jsem na situaci, kdy by se to na něčem změnilo. ' Myslím, že ' pouze " dobrá praxe " která vymře.
  • Uvozovky jsou důležité pro soubory, jejichž názvy mají mezery.
  • @ naught101 Ne, uvozovky mohou být potřebné v některých nestandardních skořápkách, například fish a csh, ale rozhodně nejsou potřeba v skořápkách podobných POSIX (sh, dash, bash, zsh, ksh, yash).

Odpověď

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

Komentáře

  • @Gilles: Divy divného zpracování -c ' 0 $ mě přiměje myslet si, že je to špatné pokaždé, když se na to podívám, ale je to rozhodně správné.
  • Líbí se mi definování explicitního prostředí …
  • Tato odpověď (a Giles ' s swer) se jeví jako lepší odpověď na otázku vzhledem k sh -c.

Odpovědi

Váš příkaz je shellem nejprve rozebrán na dva příkazy oddělené ;, což odpovídá novému řádku:

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

Chcete-li spustit příkaz prostředí, vyvolejte prostředí explicitně pomocí bash -c (nebo sh -c pokud nezajímá vás, že je shell konkrétně bash):

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

Všimněte si použití {} jako argument pro shell; je to nultý argument (což je obvykle název shellu nebo skriptu, ale zde to na tom nezáleží), proto odkazovaný jako "$0".

Do shellu můžete předat více názvů souborů najednou a nechat jimi iteraci iterovat, bude to „rychlejší. Tady předávám _ jako název skriptu a následující argumenty jsou názvy souborů, které for x (zkratka pro for x in "$@") iteruje.

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

Všimněte si, že od verze bash 4 nebo v zsh zde nemusíte vůbec hledat. V bash spusťte shopt -s globstar (vložte jej do ~/.bashrc) a aktivujte **/ kandidující na rekurzivní adresářový glob. (V zsh je to aktivní po celou dobu.) Potom

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

nebo pokud chcete, aby byly soubory iterovány v pořadí

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

Jedním rozdílem v příkazu find je, že shell ignoruje tečkové soubory (soubory, jejichž název začíná . ). Chcete-li je zahrnout, v bash nejprve nastavte GLOBIGNORE=.:..; v zsh použijte **/*(D) jako vzor glob.

Komentáře

  • Tato odpověď (a odpověď Glenna ') se jeví jako lepší odpověď na otázku danou sh -c.
  • chgrp i chmod-R možnost rekurzivního provozu.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *