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
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
acsh
, 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
ichmod
má-R
možnost rekurzivního provozu.
-name "*"
odpovídá každému jménu, takže je ' sa no-op test, který lze odstranit. Takéchmod
achgrp
má-R
možnost rekurzivního provozu.