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í:
-prunezabraňuje find v sestupu do adresáře. Jinými slovy-prunepřeskočí obsah adresáře. Ve vašem případě-name b -pruneznamená, že když find dosáhne adresáře s názvembpřeskočí adresář včetně všech podadresářů.-depthumožňuje find zpracovat obsah adresáře před samotným adresářem. To znamená, že v době, kdy find zpracuje položku adresářebjeho obsah byl již zpracován. Tedy-pruneje neúčinný s-depthve skutečnosti.-deleteimplikuje-depthtakže může nejprve smazat obsah a poté prázdný adresář.-deleteodmí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