Dateien auflisten, die mit einem Muster übereinstimmen, aber Dateien ignorieren, die mit einem anderen Muster übereinstimmen?

12

Angenommen, ich habe ein Verzeichnis mit den Dateien a1, a2, a3, b1, b2, b3. Ich möchte nur Dateien finden, die anfangen, aaber keine enthalten 3. Ich habe es versucht, ls -I "*3" *a*aber es kehrt zurück a1 a2 a3, obwohl ich nicht möchte, dass es übereinstimmt a3. Ist das möglich mit ls?

Steven
quelle
Interessante und vielfältige Antworten, aber eine Erklärung, warum ls -I '* 3' a * fehlschlägt, wäre erbaulich. und / oder warum wird die Globbed-Liste der Shell nicht anschließend durch den Ignore-Schalter auf ls gefiltert?
Theophrastus
Die Manpage sagt über die Option -I: do not list implied entries matching shell PATTERN, aber es nicht erklären , was gemeint ist mit impliziert , aber ich vermute , es nur auf Dateien angewandt wird, die lsdurch glob Erweiterungen bekommt - und lsnicht die nicht erweitern a*, die Shell tut, .
Murray Jensen

Antworten:

14

Gerade:

shopt -s extglob  
ls a!(*3*)
  • shopt -s extglob Aktiviert erweitertes Globbing.
  • a passt zum Start a
  • !()annulliert das Streichholz im ()...
    • *3*was ist 3und irgendetwas davor oder danach.

$ touch 1 2 3 a1 a2 a3 b1 b2 b3 aa1 aa2 aa3 a2a a3a
$ ls a!(*3*)
a1  a2  a2a  aa1  aa2
Chaos
quelle
1
Zu Ihrer Information, erfordertset -s extglob
Brian
@ Brian Yea, gerade bemerkt ^^
Chaos
8

Bestehende Antworten geben den besten Weg an, dies mit Globs zu tun. Ich werde dies einschließen, da in den meisten Fällen findeine bessere Option ist, wenn Sie Skripte erstellen oder weiter verarbeiten möchten:

$ find . -maxdepth 1 -name 'a*' -not -name '*3*'
./a1
./a2

Sie können die Antwort an xargseinfache Aktionen oder an eine while readSchleife für kompliziertere Dinge senden.

Tom Hunt
quelle
4

Ein einfacher Weg ist

  • um alle passenden Dateien aufzulisten a*
  • dann lösche alle Zeilen mit a 3

Der UNIX-Befehl lautet

ls -1 a* | grep -v 3

ls -1 zeigt eine Datei pro Zeile.

grepNormalerweise werden Linien gefunden, die mit einem Muster übereinstimmen, aber -vdieses Verhalten ist invertiert.

Peter K
quelle
2
Hallo Peter! Erklären Sie am besten so ausführlich wie möglich, wie Ihre Lösung funktioniert.
Dhag
2
Parsing lsist keine gute Idee: mywiki.wooledge.org/ParsingLs
Chaos
3

Mit zsh, unter Verwendung des ~ Glob-Operators :

setopt extendedglob
print -rl -- a*~*3*

Mit gnu lskönnten Sie zwei --ignoreMöglichkeiten nutzen:

ls -I '[^a]*' -I '*3*'

Die erste ignoriert alle Dateinamen, die nicht mit "" beginnen, aund die zweite ignoriert Dateinamen, die "" enthalten3

don_crissti
quelle