Multidigit-Dateibereiche in lexikografischer Reihenfolge in zsh

24

Ich möchte einen Bereich von Dateien (in lexikografischer Reihenfolge) mit zwei Ganzzahlen (z. B. 2 bis 57) in zsh durch Globbing angeben.

Zum Beispiel: "Wählen Sie die Dateien 2 bis 57 in lexikografischer Reihenfolge unter dem Pfad aus, der einem Muster entspricht".

Ich dachte mit eckigen Klammern würde es tun

 for x in /foo/bar/*[2-57]; do print $x; done

aber zsh offenbar denkt bitte ich für die Dateien 2zu 5(oder so ähnlich) anstelle von Dateien 2zu 57. Irgendwelche Gedanken warum? Wie kann ich das erreichen?

Amelio Vazquez-Reina
quelle

Antworten:

30

[2-57]Set ist ein Zeichen , bestehend aus 2, 3, 4, 5und 7, in zsh und jedem anderen Platzhalter und regexp Syntax gibt. Ihr Glob-Muster *[2-57]entspricht jedem Dateinamen, dessen letztes Zeichen eine dieser fünf Ziffern ist.

Ich denke, Sie erinnern sich falsch an die Syntax des [m,n] Glob-Qualifiers . Glob-Qualifikatoren stehen immer in Klammern am Ende des Musters, und das Bereichstrennzeichen ist ein Komma. Das Muster wird *([2,57])auf die 2., 3.,…, 57. Übereinstimmung erweitert. Die Standard-Erweiterungsreihenfolge ist lexikografisch (mit etwas Magie, um Zahlen in numerischer Reihenfolge zu sortieren, wenn die numeric_glob_sortOption aktiviert ist). Sie können es mit dem Qualifier ooder Oglob steuern (z. B. *(om[2,57])um die 57 aktuellste Datei mit Ausnahme der einen aktuellsten Datei zu finden).

for x in /foo/bar/*([2,57]); do print $x; done

Nicht das, wonach Sie gefragt haben, aber verwandt und möglicherweise nützlich für zukünftige Leser: Wenn Sie die Dateien 2 bis 57 auflisten möchten, ob sie vorhanden sind oder nicht, können Sie einen Ausdruck in geschweiften Klammern verwenden . Diese Funktion gibt es auch in bash und ksh.

echo hello{2..57}

Und wenn Sie Dateien zuordnen möchten, deren Name eine Zahl zwischen 2 und 57 enthält, können Sie das Muster verwenden <2-57>. Dies ist spezifisch für zsh.

$ ls
file1 file2 file3 file57 file58
$ echo file<2-57>
file2 file3 file57

Beachten Sie, dass ein Muster wie *<2-57>das wahrscheinlich nicht das tut, was Sie erwarten, da es *auch mit Ziffern übereinstimmen könnte. Zum Beispiel file58Übereinstimmungen *<2-57>mit file5dem *Teil und 8dem <2-57>Teil. Das Muster *[^0-9]<2-57>vermeidet dieses Problem.

Gilles 'SO - hör auf böse zu sein'
quelle
Du hast recht. Ich habe mich falsch an das Glob-Qualifikationsspiel erinnert. Vielen Dank für die sorgfältige Erklärung.
Amelio Vazquez-Reina
By the way, bekam diese Aussage mich ein wenig verwirrt: if you want to enumerate files 2 to 57 whether they exist or not, you can use a range brace expression. Wenn die Dateien nicht vorhanden sind und keine Übereinstimmungen vorliegen, wie kann die geschweifte Klammer erweitert werden? (Wie würde es anders ausbauen als im Glob-Qualifikationsspiel?)
Amelio Vazquez-Reina
2
@intrpc foo{8..11}barerweitert auf foo8bar foo9bar foo10bar foo11bar. Diese Erweiterung hat nichts mit Dateinamen zu tun. Ebenso foo{eight,nine,ten,eleven}barerweitert um fooeightbar fooninebar footenbar fooelevenbar. Dies ist die Klammererweiterung in ksh / bash / zsh.
Gilles 'SO- hör auf böse zu sein'
6

aber zsh glaubt anscheinend, ich frage nach den Dateien 2 bis 5 (oder so ähnlich) anstatt nach den Dateien 2 bis 57. Irgendwelche Gedanken warum?

Da []Klammern eine Liste übereinstimmender Zeichen (die Ziffern sein können) angeben , werden Zahlen nicht mathematisch interpretiert. Ein solches Muster wird mit einem einzelnen Zeichen abgeglichen . Die Liste kann Bereiche, aber auch Ziffern oder Buchstaben enthalten. [2-57]Die Übereinstimmung wird zu "Alle Ziffern im Bereich von 2 bis 5 und eine 7" erweitert .

Um die Zahlen von 2 bis 57 abzugleichen, ist es einfacher, einen Sequenzausdruck anstelle eines Globbing-Musters (oder zusammen mit einem solchen) zu verwenden:

for x in /foo/bar/*{2..57}; do print $x; done

Bearbeiten : Aber dies gibt Ihnen leider keine lexikografische Reihenfolge aller aufgelisteten Dateien - sie würden aufgrund der Shell-Erweiterung nach gemeinsamen Zahlenenden gruppiert.

rozcietrzewiacz
quelle
Danke @rozcietrzewiacz! Ich hätte darüber nachdenken sollen. Meine Akten enthielten Zahlen, also dachte ich für einen Moment, ich würde die []Dinge in der
richtigen
Ihre Erklärung von [2-57]ist korrekt, aber ich denke nicht, {2..57}dass (das haben Sie gemeint, richtig?) Relevant ist für das, was intrpc tun möchte, nämlich "die Dateien 2 bis 57 in lexikographischer Reihenfolge auswählen".
Gilles 'SO- hör auf böse zu sein'
Vielen Dank für die Bearbeitung (Zeit, schlafen zu gehen, denke ich). Und Sie haben Recht - ich hatte den Teil der lexikografischen Reihenfolge vergessen .
Rozcietrzewiacz