Chci rekurzivně smazat všechny soubory, ke kterým se za chvíli ve složce a
nepřistoupilo , kromě všech souborů v podsložce b
.
find a ( -name b -prune ) -o -type f -delete
Zobrazuje se mi však chybová zpráva:
find:Akce -delete automaticky zapne -depth, ale -prune nedělá
nic, když je aktivní -depth. Pokud přesto chcete pokračovat,
jednoduše použijte volbu -depth.
Přidání -depth
způsobí všechny soubory v b
být zahrnut, což nesmí ne stalo.
Zná někdo bezpečný způsob, jak to udělat?
Přijatá odpověď:
jeden způsob je použít -exec rm
místo -delete
.
find a ( -name b -prune ) -o -type f -exec rm {} +
případně použijte -not -path
místo -prune
:
find a -not -path "*/b*" -type f -delete
Vysvětlení proč -prune
koliduje s -delete
:
najít stížnosti, když se pokusíte použít -delete
pomocí -prune
protože -delete
implikuje -depth
a -depth
dělá -prune
neúčinné.
pozorovat chování find s a bez -depth
:
$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2
Neexistuje žádná záruka ohledně objednávky v jednom adresáři. Existuje však záruka, že adresář je zpracován před jeho obsahem. Poznámka foo/
před libovolným foo/*
a foo/bar
před libovolným foo/bar/*
.
To lze zvrátit pomocí -depth
.
$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/
Všimněte si, že nyní všechny foo/*
objeví se před foo/
. Totéž s foo/bar
.
další vysvětlení:
-prune
zabraňuje find v sestupu do adresáře. Jinými slovy-prune
přeskočí obsah adresáře. Ve vašem případě-name b -prune
znamená, že když find dosáhne adresáře s názvemb
přeskočí adresář včetně všech podadresářů.-depth
umožňuje find zpracovat obsah adresáře před samotným adresářem. To znamená, že v době, kdy find zpracuje položku adresářeb
jeho obsah byl již zpracován. Tedy-prune
je neúčinný s-depth
ve skutečnosti.-delete
implikuje-depth
takže může nejprve smazat obsah a poté prázdný adresář.-delete
odmítá smazat neprázdné adresáře.
Vysvětlení alternativní metody:
find a -not -path "*/b*" -type f -delete
To může, ale nemusí být jednodušší na zapamatování.
Tento příkaz stále sestupuje do adresáře b
a zpracovává každý jednotlivý soubor v něm pouze pro -not
odmítnout je. To může být problém s výkonem, pokud je adresář b
je obrovský.
-path
funguje jinak než -name
. -name
odpovídá pouze názvu (souboru nebo adresáře), zatímco -path
odpovídá celé cestě. Sledujte například cestu /home/lesmana/foo/bar
. -name bar
bude odpovídat, protože název je bar
. -path "*/foo*"
bude odpovídat, protože řetězec /foo
je v cestě. -path
má některé složitosti, kterým byste měli porozumět, než jej použijete. Přečtěte si manuálovou stránku find
pro více podrobností.
Pozor, toto není 100% spolehlivé. Existuje možnost „falešných poplachů“. Způsob, jakým je příkaz napsán výše, přeskočí jakýkoli soubor, který má jakýkoli nadřazený adresář, jehož název začíná b
(pozitivní). Ale také přeskočí jakýkoli soubor, jehož název začíná b
bez ohledu na pozici ve stromu (falešně pozitivní). To lze opravit napsáním lepšího výrazu než "*/b*"
. To je ponecháno jako cvičení pro čtenáře.
Předpokládám, že jste použili a
a b
jako zástupné symboly a skutečná jména jsou spíše allosaurus
a brachiosaurus
. Pokud vložíte brachiosaurus
místo b
pak se množství falešně pozitivních výsledků drasticky sníží.
Alespoň falešně pozitivní budou ne smazáno, tak to nebude tak tragické. Kromě toho můžete zkontrolovat falešné poplachy tak, že nejprve spustíte příkaz bez -delete
(ale nezapomeňte umístit implikovaný -depth
) a prozkoumejte výstup.
find a -not -path "*/b*" -type f -depth