Die Syntax a*
und *a*
wird von der Shell und nicht vom ls
Befehl implementiert .
Wenn Sie tippen
ls a*
An der Shell-Eingabeaufforderung wird die Shell a*
zu einer Liste aller im aktuellen Verzeichnis vorhandenen Dateien erweitert , deren Namen mit beginnen a
. Beispielsweise kann es a*
auf die Sequenz erweitert a1 a2 a3
und diese als Argumente an übergeben werden ls
. Der ls
Befehl selbst sieht den *
Charakter nie ; es sieht nur die drei Argumente a1
, a2
und a3
.
Für die Platzhaltererweiterung bezieht sich "Dateien" auf alle Entitäten im aktuellen Verzeichnis. Dies kann beispielsweise a1
eine normale Datei, a2
ein Verzeichnis oder a3
ein Symlink sein. Sie haben alle Verzeichniseinträge, und es ist der Platzhaltererweiterung der Shell egal, auf welche Art von Entität sich diese Einträge beziehen.
Praktisch alle Shells, auf die Sie wahrscheinlich stoßen (bash, sh, ksh, zsh, csh, tcsh, ...), implementieren Platzhalter. Die Details können variieren, aber die grundlegende Syntax des *
Abgleichs von null oder mehr Zeichen und des ?
Abgleichs eines einzelnen Zeichens ist einigermaßen konsistent.
Insbesondere für Bash ist dies im Abschnitt "Dateinamenerweiterung" des Bash-Handbuchs dokumentiert. starte info bash
und suche nach "Dateinamenerweiterung", oder sieh hier .
Die Tatsache, dass dies von der Shell und nicht von einzelnen Befehlen ausgeführt wird, hat einige interessante (und manchmal überraschende) Konsequenzen. Das Beste daran ist, dass der Umgang mit Platzhaltern für (fast) alle Befehle konsistent ist . Wenn die Shell dies nicht tun würde, würden sich einige Befehle zwangsläufig nicht darum kümmern, und andere würden es auf subtile Weise tun, die der Autor für "besser" hielt. (Ich denke, die Windows-Befehlsshell hat dieses Problem, aber ich kenne es nicht gut genug, um weitere Kommentare abzugeben.)
Andererseits ist es schwierig, einen Befehl zum Umbenennen mehrerer Dateien zu schreiben. Wenn du schreibst:
mv *.log *.log.bak
Es wird wahrscheinlich fehlschlagen, da *.log.bak
es basierend auf den Dateien, die bereits im aktuellen Verzeichnis vorhanden sind, erweitert wird. Es gibt Befehle, die so etwas tun, aber sie müssen ihre eigene Syntax verwenden, um anzugeben, wie die Dateien umbenannt werden sollen. Einige Befehle (z. B. find
) können ihre eigene Platzhaltererweiterung ausführen . Sie müssen die Argumente angeben, um die Erweiterung der Shell zu unterdrücken:
find . -name '*.txt' -print
Die Platzhaltererweiterung der Shell basiert ausschließlich auf der Syntax des Befehlszeilenarguments und der Menge der vorhandenen Dateien. Es kann nicht durch die Bedeutung des Befehls beeinflusst werden. Wenn Sie beispielsweise alle .log
Dateien in das übergeordnete Verzeichnis verschieben möchten , können Sie Folgendes eingeben:
mv *.log ..
Wenn Sie das vergessen ..
:
mv *.log
und es gibt zufällig genau zwei .log
Dateien im aktuellen Verzeichnis, es wird erweitert auf:
mv one.log two.log
die wird umbenennen one.log
und clobber two.log
.
EDIT : Und nach 52 Upvotes, einem Accept und einem Guru-Badge sollte ich vielleicht die Frage im Titel beantworten.
Die Option -d
oder sagt nicht, dass nur Verzeichnisse aufgelistet werden sollen. Es weist es an, Verzeichnisse nur als sich selbst aufzulisten, nicht als deren Inhalt. Wenn Sie einen Verzeichnisnamen als Argument angeben , wird standardmäßig der Inhalt des Verzeichnisses aufgelistet , da dies normalerweise für Sie von Interesse ist. Mit dieser Option wird festgelegt, dass nur das Verzeichnis selbst aufgelistet wird. Dies kann insbesondere in Kombination mit Platzhaltern hilfreich sein. Wenn Sie Folgendes eingeben:--directory
ls
ls
-d
ls -l a*
ls
Sie erhalten eine lange Liste aller Dateien, deren Name mit "" beginnt a
, sowie der Inhalte aller Verzeichnisse, deren Name mit "" beginnt a
. Wenn Sie nur eine Liste der Dateien und Verzeichnisse mit jeweils einer Zeile benötigen, können Sie Folgendes verwenden:
ls -ld a*
was äquivalent ist zu:
ls -l -d a*
Denken Sie erneut daran, dass der ls
Befehl das *
Zeichen nie sieht .
Wo dies dokumentiert ist, man ls
zeigt Ihnen die Dokumentation für den ls
Befehl auf nahezu jedem Unix-ähnlichen System. Auf den meisten Linux-basierten Systemen ist der ls
Befehl Teil des GNU-Pakets coreutils. wenn Sie die haben info
Befehl, entweder info ls
oder info coreutils ls
sollten Sie mehr endgültige und umfassende Dokumentation geben. Andere Systeme, wie z. B. MacOS, verwenden möglicherweise andere Versionen des ls
Befehls und verfügen möglicherweise nicht über den info
Befehl. Verwenden Sie für diese Systeme man ls
. Und ls --help
zeigt eine relativ kurze Verwendungsmeldung (117 Zeilen auf meinem System), wenn Sie die GNU-Coreutils-Implementierung verwenden.
Und ja, auch Experten müssen ab und zu die Dokumentation konsultieren. Siehe auch diesen klassischen Witz .