Was ist der Unterschied zwischen ls [13] und ls {1,3}?

11

Ich habe mit dem Befehl drei Dateien in meinem Verzeichnis erstellt touch inv{1..3}.txt. Jetzt habe ich zwei Befehle verwendet und ihre Ausgabe ist ziemlich gleich. Diese beiden Befehle sind ls inv[13].txtund ls {1,3}.txt.

Wie unterscheiden sich diese beiden? Wie unterscheiden sich eckige Klammern von geschweiften Klammern? Ich habe auch nach "Linux [..]" gegoogelt, konnte aber nichts finden. Könnte ich also wissen, wie diese Dinge in der Linux-Terminologie heißen?

Vielen Dank

posixKing
quelle
2
Der Name hierfür ist "Dateinamenerweiterung" oder "Globbing".
Byte Commander
Welche davon ist Dateinamenerweiterung oder Globbing? Ist es die eckige Klammer ([..]) oder die Blumenklammer ({..})?
posixKing
Besuchen Sie Klammererweiterung für {}und Dateinamenerweiterung> Musterabgleich für [].
Pandya

Antworten:

14
  • {}wird Klammererweiterung genannt. Es gibt zwei Formen: {x..y}und {x,y}, ersetzen xund ydurch einen beliebigen alphabetischen oder numerischen Wert.

    In der ersten Form {x..y}wird auf alle Werte von xbis yeinschließlich erweitert. Zum Beispiel {2..5}wird erweitert werden 2, 3, 4, 5.

    In der zweiten expliziten Form {x,y}wird nur auf x, y. Zum Beispiel {2,5}wird erweitert 2und 5.

    Wenn keine Erweiterung möglich ist, wird das Muster wörtlich behandelt, z {a..3}. B. in .

    Es ist wichtig zu beachten, dass die Klammererweiterung (wenn möglich) unabhängig von einer Dateianpassung während der Dateierstellung / -anpassung durchgeführt wird.

  • []ist als Pfadnamen-Erweiterungsmuster (oder Globbing-Muster) bekannt. Im Gegensatz zur Klammererweiterung können Sie sie nur verwenden, wenn Sie mit Dateinamen übereinstimmen. Sie wird buchstäblich behandelt, wenn Sie sie beim Erstellen von Dateien verwenden.

    Es hat zwei Formen: [xyz...]und [x-y].

    In der ersten Form wird jedes einzelne Zeichen in den eckigen Klammern separat abgeglichen, dh jedes Zeichen wird einzeln behandelt. Also für [25].txtes wird eine Datei mit dem Namen übereinstimmen 2.txtoder 5.txtim aktuellen Verzeichnis, während für [245].txtsie eine beliebige Datei mit dem Namen übereinstimmen 2.txtoder 4.txtoder 5.txt.

    In der zweiten Form wird zuerst eine Bereichserweiterung durchgeführt, bevor sie einzeln abgeglichen wird, wenn dies anderweitig wörtlich behandelt wird. Daher stimmt [2-5]. txtes mit jeder Datei mit dem Namen 2.txtoder 3.txtoder 4.txtoder überein 5.txt. Wenn der Bereich nicht erweitert werden kann, wird er buchstäblich behandelt, z [a-3].txt.


Ein wichtiger Verhaltensunterschied zwischen diesen beiden besteht darin, dass mehr Muster übereinstimmen müssen, während weniger tatsächlich übereinstimmen. Da die Klammererweiterung auf jeden Fall durchgeführt wird, wird der Fehler angezeigt, dass bestimmte Dateien nicht vorhanden sind, während die Pfadnamenerweiterung mit allen möglichen Fehlern übereinstimmt.

$ ls {1..4}.txt
ls: cannot access 4.txt: No such file or directory
1.txt  2.txt  3.txt

$ ls [1-4].txt
1.txt  2.txt  3.txt

Portabilitätshinweis:

Der []Pfadnamen-Erweiterungsoperator wird von POSIX definiert und ist daher zwischen Bourne-Shell und Derivaten portierbar.

Die Klammererweiterung {}wird von POSIX nicht definiert und ist daher nicht für alle Schalen tragbar. Zum Beispiel dash( shin Ubuntu) hat dies nicht. Es wurde entlehnt cshund wird auf bestimmte Schalen arbeitet nur zum Beispiel bash, zsh, ksh93, fish. Stellen Sie sicher, dass die von Ihnen verwendete Shell dies unterstützt, bevor Sie sie implementieren.


Beispiel:

$ touch {1..3}.txt

$ ls {1..3}.txt
1.txt  2.txt  3.txt

$ ls {1,2,3}.txt
1.txt  2.txt  3.txt

$ ls {1..4}.txt
ls: cannot access 4.txt: No such file or directory
1.txt  2.txt  3.txt

$ ls {a..3}.txt
ls: cannot access {a..3}.txt: No such file or directory

$ ls [123].txt
1.txt  2.txt  3.txt

$ ls [1-3].txt
1.txt  2.txt  3.txt

$ ls [1-4].txt
1.txt  2.txt  3.txt

$ ls [a-3].txt
ls: cannot access [a-3].txt: No such file or directory
heemayl
quelle
1
Man sollte es vermeiden, sich auf das Verhalten der [ ]Erweiterung zu verlassen, wenn es keine Übereinstimmungen gibt, da dies je nach Shell-Konfiguration unterschiedlich sein kann. Wenn Sie [oder ]in einem Dateinamen verwenden möchten , sollte dieser in Ihren Befehlen angegeben werden. Es lohnt sich auch, den Unterschied zwischen {13..79}und zu bemerken [13-79]. Die erste wird alle Zahlen im Bereich erzeugen aus 13zu 79, die zweite die Zeichen übereinstimmen 1, 3, 4, 5, 6, 7, und 9.
Kasperd
@kasperd Ja, dafür ist nullglob(oder ähnliches) gedacht . Über das [13-79]Matching habe ich in meiner Antwort das Verhalten pro Zeichen von [] `deutlich erwähnt.
Heemayl
@heemayl Ich denke, es wäre auch erwähnenswert, dass `{1..3}` Form Bashismus ist. Dies funktioniert nicht im Bindestrich. Ich denke, kshhat diese Funktion, aber es ist nicht moderner Aromen, wie mksh und pkdsh
Sergiy Kolodyazhnyy
@Serg Die Portabilitätsnotiz wurde hinzugefügt.
Heemayl
7

Der Hauptunterschied zwischen den beiden Formen ist hier dargestellt:

$ ls inv[15].txt
inv1.txt
$ ls inv{1,5}.txt
ls: cannot access 'inv5.txt': No such file or directory
inv1.txt

inv[15].txtist ein Glob und erweitert die Liste der übereinstimmenden Dateien in Ihrem Dateisystem. Dies ist eine Pfadnamenerweiterung .

inv{1,5}.txtErweitert auf inv1.txtund inv5.txtunabhängig davon, welche Dateien sich tatsächlich in Ihrem Dateisystem befinden. Dies ist eine Klammererweiterung .

John1024
quelle
Der andere wesentliche Unterschied besteht darin, dass Sie schreiben können ba{con,tman}und es kein Äquivalent in eckigen Klammern gibt. IOW, die Klammererweiterung gilt nicht nur für einzelne Zeichen.
Hobbs