Řekněme, že mám adresář s více soubory, z nichž všechny jsou buď binární soubory (soubory bez deklarovaných přípon) a zdrojové soubory (.c
rozšíření). Dělám toto:
$ ls
a získejte:
README.md hello-world.c hello-world get-name.c get-name
a chci vypsat pouze soubory se specifickými příponami (řekněme oba .c
a .md
), já ano:
ls *.c *.md
a to je v pořádku!
Ale co když teď chci smazat všechny soubory, které nedělají mít .c
nebo .md
rozšíření, jak to mohu udělat?
Vím, jak to udělat se soubory, jejichž přípony jsou mi známé, jako:
ls *.c *.md | xargs rm
Ale jak přikážu příkazovému řádku, aby smazal soubory, které NEDÁ vyhovuje mým kritériím?
Přijatá odpověď:
Použijte find
:
find -maxdepth 1 ! -name "*.c" -print0 | xargs -0 ...
Všimněte si, že -maxdepth
, -print0
, -r
a -0
se nacházejí v několika find
implementace (byly představeny GNU find
/xargs
), ale nejsou specifikovány POSIX. Dalším způsobem je, jak Stéphane zmínil ve svém komentáři, použití -exec
akce find – nezapomeňte použít příkaz -exec command {} +
formulář, protože dramaticky snižuje počet vyvolání command
(musí však povolit syntaxi, kde jsou názvy souborů umístěny na konci, jinak musíte zabalit command
uvnitř sh -c
zavolat).
Případně grep
výstup ls
ls | grep -v ".c$" | xargs ...
Několik rozšíření můžete filtrovat buď pomocí regulárních výrazů:
... | grep -v ".(c|md)$" | ...
s rozšířenými regulárními výrazy:
... | grep -Ev ".(c|md)$" | ...
s možností pevných řetězců (nebude se shodovat pouze na konci názvu souboru!):
... | grep -vF ".c
.md" | ...
nebo zřetězením více grep
s:
... | grep -v ".c$" | grep -v ".md$" | ...
To znamená, find
je pravděpodobně nejlepší volbou, protože s -print0
tato možnost zpracovává všechny možné znaky v názvech souborů, které by jinak mohly vyžadovat escapování (za předpokladu, že find
a xargs
jsou schopni pracovat s řetězci zakončenými NULL – např. nástroje GNU jsou).