Entfernen Sie alle Dateitypen bis auf einen (oder mehrere)

20

Ich habe versucht, einen Befehl zum Entfernen aller Dateien in einem Ordner zu finden, aber keine Art von Dateityp. Aber ich scheine kein Glück zu haben. Was ich bisher ausprobiert habe:

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

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

Die Version von zsh, die ich verwende, ist zsh 5.0.2 (x86_64-apple-darwin13.0.1).

nXqd
quelle

Antworten:

22

Die extended_globOption gibt Ihnen die eigene erweiterte Glob-Syntax von zsh .

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

Sie können die ksh_globOption zum Abrufen von ksh-Globs festlegen . Beachten Sie, dass zsh im allgemeinen Fall, in dem das negative Muster das letzte Element im Wort ist, die Klammern möglicherweise als Glob-Qualifikationsmerkmale parst (dies geschieht nicht im ksh-Emulationsmodus).

setopt ksh_glob
rm -- !(*.dmg|*.txt)
setopt no_bare_glob_qual
rm -- !(*.dmg)
Gilles 'SO - hör auf böse zu sein'
quelle
Das scheint nicht zu funktionieren. Wenn ich rm -r secrets/!(directory)number expectedevent not found: directory
renne, frage
@CMCDragonkai "Zahl erwartet" zeigt an, dass Sie die ksh_globOption nicht eingestellt haben . "Event not found: directory" zeigt an, dass Sie bash ausführen (was auch die !(…)Syntax versteht, aber nur danach shopt -s extglob).
Gilles 'SO- hör auf böse zu sein'
Wie könnte ich bash ausführen, wenn ich in meiner zsh-Shell war?
CMCDragonkai
Bei mir setopt ksh_glob; echo !(a|b)funktioniert, während setopt ksh_glob; echo !(a)nicht ("Nummer erwartet") ...
ThiefMaster
@ ThiefMaster Ich hatte das gleiche Problem. Ist es ein Bug?
CodeTower
5

Sie können findanstelle Ihrer Shell verwenden:

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

Von 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.

Wenn Sie findaus irgendeinem Grund nicht verwenden können , haben Sie hier eine Möglichkeit, dies mit zsh(oder anderen Muscheln) zu tun . zshSein zsh, gibt es wahrscheinlich einen einfacheren Weg , dies zu tun , aber da ich bin bashKerl, das ist , was mit ich kam:

for file in *; do if [[ ! "$file" == *.dmg ]]; then rm $file; fi; done
terdon
quelle
Wenn ich find auf meinem Mac verwende, wird die aktuelle zsh-Sitzung leider ohne Vorankündigung beendet. Hast du das selbe problem find [Process completed]
nXqd
1
@nXqd siehe aktualisierte Antwort für eine Möglichkeit, es ohne zu tun find. Ich schlage vor, dass Sie eine Frage zu Ihrem findProblem stellen. Dies sollte jedoch nicht passieren. Wenn Sie dies tun, schließen Sie die Ausgabe von ein type -a find.
Terdon
1
Auch in Bash gibt es eine einfachere Lösung: rm !(*.dmg)nach shopt -s extglob.
Gilles 'SO- hör auf böse zu sein'
@terdon danke für deine Tipps zum Debuggen in der Shell. Die Ausgabe scheint korrekt zu sein:find is a shell function find is /usr/bin/find
nXqd
@nXqd das ist nicht korrekt, es sollte keine Shell-Funktion sein, es sollte nur sein /usr/bin/find. Sie haben eine Funktion, finddie in einer Ihrer Bash-Konfigurationsdateien definiert ist. Da Sie auf OSX sind, ist das wahrscheinlich ~/.profile.
terdon
3

Eine andere Möglichkeit , Dateien zu entfernen , ist mit find, xargsund rm:

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