Was bedeutet. ?? * in einem Shell-Befehl?

22

Der folgende Befehl tar"punktiert" alle Dateien und Ordner:

tar -zcvf dotfiles.tar.gz .??*

Ich kenne mich mit regulären Ausdrücken aus , verstehe aber nicht, wie man sie interpretiert .??*. Ich habe ls .??*und ausgeführt und mir tree .??*die aufgelisteten Dateien angesehen. Warum enthält dieser reguläre Ausdruck alle Dateien in Ordnern, die .beispielsweise mit beginnen?

SabreWolfy
quelle

Antworten:

32

Globs sind keine regulären Ausdrücke. Im Allgemeinen versucht die Shell, alle Eingaben in der Befehlszeile zu interpretieren, die Sie nicht als Glob angeben. Shells müssen überhaupt keine regulären Ausdrücke unterstützen (obwohl es in Wirklichkeit viele der schickeren, moderneren tun, z. B. die=~ Regex-Match-Operator im bash [[Konstrukt).

Das .??*ist ein Glob. Es stimmt mit jedem Dateinamen überein, der mit einem wörtlichen Punkt beginnt ., gefolgt von zwei beliebigen (nicht unbedingt gleichen) Zeichen.?? , gefolgt vom Äquivalent des regulären Ausdrucks von [^/]*, dh 0 oder mehr Zeichen, die keine sind /.

Ausführliche Informationen zur Erweiterung des Shell-Pfadnamens (vollständiger Name für "Globbing") finden Sie in der POSIX-Spezifikation .

jw013
quelle
10
Zusätzlicher Punkt: Dies ist ein Versuch, ein Glob zu schreiben, das mit allen Punktedateien in einem Verzeichnis außer den speziellen Einträgen übereinstimmt .und ..mit dem man normalerweise nichts anfangen möchte. Es ist nicht ganz richtig; Es wird nichts mit dem Namen ' .X' aufgenommen, wobei X ein anderes Zeichen als ein Punkt ist. Ich glaube nicht, dass es möglich ist, ein einzelnes Glob zu schreiben, das zu jeder Punktdatei passt, außer .und .., aber Sie können es mit zwei machen: tar zcvf dotfiles.tar.gz .[!.] .??*zum Beispiel.
zwol
@Zack: Danke für die Klarstellung. Ich habe einen Kommentar dazu gepostet, ihn dann aber gelöscht. ls .?Es wurde das Gleiche wie zurückgegeben ls .., was bedeutete, dass sich keine anderen Einträge in dem Ordner befanden, die dem Muster entsprachen .?. Ich hätte .[^.]für alle .?anderen Dateien als getan ...
SabreWolfy
2
@SabreWolfy Wenn Sie die POSIX-Spezifikation sorgfältig lesen, ist das eigentlich ein wichtiger Unterschied zwischen Globs und Regex: In Klammerausdrücken [^abc]bedeutet die Regex-Syntax dasselbe wie [!abc]in der Glob-Syntax (dh ^wird durch !für Globs ersetzt). Die Verwendung der [^abc]Stilsyntax in einem Glob ist nicht sehr portabel, da POSIX nicht ^genau angibt, was es bedeutet. Einige Shells interpretieren sie daher mit einer regulären Semantik, während andere sie nur als Literalzeichen behandeln .
JW013
1
@ jw013: Danke für die Details. Ich muss mich daran erinnern, dass glob! = Regexp :)
SabreWolfy
1
Mir ist gerade in den Sinn gekommen, dass .[!.]es tarim allgemeinen Fall, dass es keine Dateien gibt, die mit diesem Muster übereinstimmen, ein Literal in der Befehlszeile geben kann. Mit einigen Shells können Sie dieses Verhalten steuern, z. B. mit Bash, shopt -s nullglobund es wird in der Befehlszeile ausgeblendet, wenn es nicht mit irgendetwas übereinstimmt. Dies ist jedoch keine universelle Funktion.
zwol
8

Der .??*Platzhalter ( kein regulärer Ausdruck, obwohl er so aussieht) wird in Dateinamen übersetzt, die mit einem Punkt ( .) beginnen, gefolgt von zwei einzelnen Zeichen (?? ) und einer beliebigen Anzahl (null oder mehr) anderer Zeichen ( *).

Vielleicht ist diese Seite über Platzhalter in Dateinamen hilfreich.

Levon
quelle
-1

Um die anderen Antworten zu ergänzen, wird eine einzelne ?Datei in einen einzelnen Zeichendateinamen übersetzt und ??mit Dateinamen abgeglichen, die nur aus zwei Zeichen bestehen.

[root@mercy testdir_2]# ls
ion  it  r
[root@mercy  testdir_2]# ls ?
r
[root@mercy  testdir_2]# ls ??
it
[root@mercy 1 testdir_2]# ls ???
ion
[root@mercy  testdir_2]#
Sree
quelle
Downvoter, könntest du bitte einen Kommentar abgeben? Würde mich freuen, korrigiert zu werden, wenn ich mich irre.
Sree
Ihre Antwort hat die Frage nicht vollständig beantwortet.
SabreWolfy