Disons que j'ai un directory avec plusieurs files, qui sont soit des files binarys (files sans extensions déclarées) et des files source (extension .c
). Je fais ça:
$ ls
et get:
README.md hello-world.c hello-world get-name.c get-name
et je veux listr seulement les files avec des extensions spécifiques (disons .c
et .md
), je fais:
ls *.c *.md
et c'est ok!
Mais que faire si maintenant je veux supprimer tous les files qui n'ont pas d' extension .c
ou .md
, comment puis-je faire cela?
Je sais comment le faire aux files dont les extensions sont connues à moi, comme:
ls *.c *.md | xargs rm
Mais comment puis-je dire à la command line de supprimer les files qui ne correspondent pas à mes critères?
Utilisez find
:
find -maxdepth 1 ! -name "*.c" -print0 | xargs -0 ...
Notez que -maxdepth
, -print0
, -r
et -0
sont trouvés dans quelques implémentations de find
(introduites par GNU find
/ xargs
) mais ne sont pas spécifiées par POSIX. Une autre façon est, comme Stéphane l'a mentionné dans son commentaire, d'utiliser l'action -exec
de find – callbackez-vous d'utiliser la -exec command {} +
form, car cela réduit considérablement le nombre d'invocations de command
(il doit autoriser la syntaxe où les noms de files sont placés à la fin cependant, ou bien vous devez envelopper la command
intérieur d'un appel sh -c
).
Alternativement grep
la sortie de ls
ls | grep -v "\.c$" | xargs ...
Vous pouvez filterr plusieurs extensions avec des expressions régulières:
... | grep -v "\.\(c\|md\)$" | ...
avec des expressions rationnelles étendues:
... | grep -Ev "\.(c|md)$" | ...
avec l'option de strings fixes (ne correspondra pas juste à la fin du nom de file!):
... | grep -vF ".c .md" | ...
ou en enchaînant plus de grep
s:
... | grep -v "\.c$" | grep -v "\.md$" | ...
Cela dit, find
est probablement la meilleure option, car avec l'option -print0
, elle gère tous les caractères possibles dans les noms de files qui pourraient avoir besoin de s'échapper autrement (à condition que votre find
et xargs
puissent fonctionner avec des strings terminées par NULL) .
En ksh
, vous pouvez utiliser:
rm -- !(*.c|*.md)
Ces extensions globbing sont également disponibles dans bash
après shopt -s extglob
et dans zsh
après setopt kshglob
.
Voici l'équivalent natif de zsh:
setopt extended_glob rm -- ^(*.c|*.md)
Le !
dans un extglob est "pas". Pour votre command originale, il est préférable d'écrire ceci:
rm -- *.c *.md
L'parsing de la sortie de ls
n'est pas fiable et va se briser sur certains noms de files. Voir le bash wiki pour l' parsing ls .