Obtenir le complément du résultat d'une command ls

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 .