Supprimer tous les types de fichiers sauf un (ou plusieurs)

20

J'ai essayé de trouver une commande pour supprimer tous les fichiers d'un dossier, mais pas une sorte de type de fichier. Mais il me semble que je n'ai pas de chance. Ce que j'ai essayé jusqu'à présent:

set extended_glob
rm !(*.dmg)
# this returns zsh:number expected

rm ./^*.dmg
# this returns no matches found 

La version de zsh que j'utilise est zsh 5.0.2 (x86_64-apple-darwin13.0.1).

Dzung Nguyen
la source

Réponses:

22

L' extended_globoption vous donne la propre syntaxe de glob étendue de zsh .

setopt extended_glob
rm -- ^*.dmg
rm -- ^*.(dmg|txt)

Vous pouvez définir l' ksh_globoption pour obtenir des globes ksh . Attention, dans le cas courant où le motif négatif est la dernière chose dans le mot, zsh peut analyser les parenthèses comme qualificatifs glob (il ne le fait pas en mode d'émulation ksh).

setopt ksh_glob
rm -- !(*.dmg|*.txt)
setopt no_bare_glob_qual
rm -- !(*.dmg)
Gilles 'SO- arrête d'être méchant'
la source
Cela ne semble pas fonctionner. Quand je cours, rm -r secrets/!(directory)il me demande number expectedou parfois il me donneevent not found: directory
CMCDragonkai
@CMCDragonkai «nombre attendu» indique que vous n'avez pas défini l' ksh_globoption. «Événement non trouvé: répertoire» indique que vous exécutez bash (qui comprend également la !(…)syntaxe, mais seulement après shopt -s extglob).
Gilles 'SO- arrête d'être méchant'
Comment pourrais-je exécuter bash quand j'étais dans mon shell zsh?
CMCDragonkai
Pour moi, ça setopt ksh_glob; echo !(a|b)marche quand setopt ksh_glob; echo !(a)ça ne marche pas ("nombre attendu") ...
ThiefMaster
@ThiefMaster J'ai eu le même problème. Est-ce un bug?
CodeTower
5

Vous pouvez utiliser à la findplace de votre shell:

find . -mindepth 1 -maxdepth 1 ! -name "*.dmg" -delete

De man find:

   ! expr True  if  expr  is false.  This character will also usually need
          protection from interpretation by the shell.
   -name pattern
          Base of file name (the path with the leading directories removed)
          matches shell pattern pattern. 
   -delete
          Delete  files; true if removal succeeded.  If the removal failed,
          an error message is issued.  If -delete fails, find's exit status
          will be nonzero (when  it eventually exits).  Use of -delete 
          automatically turns on the -depth option.

Si vous ne pouvez pas l'utiliser findpour une raison quelconque, voici un moyen de le faire avec zsh(ou d'autres coquilles). zshétant zsh, il y a probablement un moyen plus simple de le faire, mais comme je suis un bashgars, voici ce que j'ai trouvé:

for file in *; do if [[ ! "$file" == *.dmg ]]; then rm $file; fi; done
terdon
la source
malheureusement, chaque fois que j'utilise find dans mon mac, il quitte simplement la session zsh en cours sans préavis. Avez-vous le même problème? find [Process completed]
Dzung Nguyen
1
@nXqd voir la réponse mise à jour pour un moyen de le faire sans find. Je vous suggère de poster une question sur votre findproblème, cela ne devrait pas se produire. Si vous le faites, incluez la sortie de type -a find.
terdon
1
Même en bash, il existe une solution plus simple:, rm !(*.dmg)après shopt -s extglob.
Gilles 'SO- arrête d'être méchant'
@terdon merci pour vos conseils de débogage dans le shell. sa sortie semble être correcte:find is a shell function find is /usr/bin/find
Dzung Nguyen
@nXqd qui n'est pas correct, il ne devrait pas s'agir d'une fonction shell, il devrait l'être /usr/bin/find. Vous avez une fonction appelée finddéfinie dans l'un de vos fichiers de configuration bash. Puisque vous êtes sur OSX, c'est probablement ~/.profile.
terdon
3

Une autre façon de supprimer des fichiers est avec find, xargset rm:

find . -mindepth 1 -maxdepth 1 ! -name '*.dmg' -print0 | xargs -0 rm
Dragos Rizescu
la source