388 Stimmen

Wie kann ich beim Mustervergleich in einer Unix/Linux-Shell inverse oder negative Platzhalter verwenden?

Angenommen, ich möchte den Inhalt eines Verzeichnisses kopieren, ohne Dateien und Ordner, deren Namen das Wort "Musik" enthalten.

cp [exclude-matches] *Music* /target_directory

Was sollte anstelle von [exclude-matches] verwendet werden, um dies zu erreichen?

434voto

Vinko Vrsalovic Punkte 252104

In der Bash können Sie dies tun, indem Sie die Option extglob Option, etwa so (ersetzen Sie ls con cp und natürlich das Zielverzeichnis hinzufügen)

~/foobar> shopt extglob
extglob        off
~/foobar> ls
abar  afoo  bbar  bfoo
~/foobar> ls !(b*)
-bash: !: event not found
~/foobar> shopt -s extglob  # Enables extglob
~/foobar> ls !(b*)
abar  afoo
~/foobar> ls !(a*)
bbar  bfoo
~/foobar> ls !(*foo)
abar  bbar

Sie können extglob später mit

shopt -u extglob

263voto

tzot Punkte 86792

Les extglob Shell-Option bietet Ihnen einen leistungsfähigeren Mustervergleich in der Befehlszeile.

Sie schalten ihn ein mit shopt -s extglob und schalten Sie sie mit shopt -u extglob .

In Ihrem Beispiel würden Sie das zunächst tun:

$ shopt -s extglob
$ cp !(*Music*) /target_directory

Die vollständig verfügbaren ext beendet Globus bing-Betreiber sind (Auszug aus man bash ):

Wenn die Shell-Option extglob mit dem buildin shopt aktiviert ist, werden mehrere erweiterte Mustervergleichsoperatoren erkannt. Eine Musterliste ist eine Liste von einem oder mehreren Mustern, die durch ein | getrennt sind. Zusammengesetzte Muster können aus einem oder mehreren der folgenden Teilmuster gebildet werden:

  • ?(Muster-Liste)
    Passt auf null oder ein Vorkommen der angegebenen Muster
  • *(Muster-Liste)
    Passt auf null oder mehr Vorkommen der angegebenen Muster
  • +(Muster-Liste)
    Entspricht einem oder mehreren Vorkommen der angegebenen Muster
  • @(Muster-Liste)
    Entspricht einem der angegebenen Muster
  • !(Muster-Liste)
    Passt auf alles außer auf eines der angegebenen Muster

Wenn Sie zum Beispiel alle Dateien im aktuellen Verzeichnis auflisten wollen, die nicht .c o .h Dateien, würden Sie das tun:

$ ls -d !(*@(.c|.h))

Natürlich funktioniert das normale Shell-Globing, so dass das letzte Beispiel auch so geschrieben werden könnte:

$ ls -d !(*.[ch])

26voto

ejgottl Punkte 2771

Nicht in Bash (soweit ich weiß), aber:

cp `ls | grep -v Music` /target_directory

Ich weiß, dass dies nicht genau das ist, wonach Sie gesucht haben, aber es wird Ihr Beispiel lösen.

12voto

Steve Punkte 571

Wenn Sie die Speicherkosten des exec-Befehls vermeiden wollen, können Sie meiner Meinung nach besser mit xargs arbeiten. Ich denke, das Folgende ist eine effizientere Alternative zu

find foo -type f ! -name '*Music*' -exec cp {} bar \; # new proc for each exec

find . -maxdepth 1 -name '*Music*' -prune -o -print0 | xargs -0 -i cp {} dest/

8voto

mivk Punkte 11443

In der Bash ist eine Alternative zu shopt -s extglob ist die GLOBIGNORE variabel . Es ist nicht wirklich besser, aber ich finde es leichter zu merken.

Ein Beispiel, das vielleicht das ist, was der ursprüngliche Poster wollte:

GLOBIGNORE="*techno*"; cp *Music* /only_good_music/

Wenn Sie fertig sind, unset GLOBIGNORE um zu können rm *techno* im Quellverzeichnis.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X