- Bei der Angabe
ls --directory a*
sollten nur Verzeichnisse aufgeführt werden, die mit beginnena*
- ABER es listet Dateien UND Verzeichnisse auf, die mit beginnen
a
Fragen :
- wo könnte ich eine Dokumentation dazu finden, außer
man
undinfo
wo glaube ich, habe ich gründlich nachgesehen? - funktioniert das nur in BASH?
echo a*
listet Ihnen auch die Dateien auf, die mita
(falls vorhanden) beginnen. Nur um klarer zu machen, dass das nichtls
so ist, sondern die Bash.Antworten:
Die Syntax
a*
und*a*
wird von der Shell und nicht vomls
Befehl implementiert .Wenn Sie tippen
An der Shell-Eingabeaufforderung wird die Shell
a*
zu einer Liste aller im aktuellen Verzeichnis vorhandenen Dateien erweitert , deren Namen mit beginnena
. Beispielsweise kann esa*
auf die Sequenz erweiterta1 a2 a3
und diese als Argumente an übergeben werdenls
. Derls
Befehl selbst sieht den*
Charakter nie ; es sieht nur die drei Argumentea1
,a2
unda3
.Für die Platzhaltererweiterung bezieht sich "Dateien" auf alle Entitäten im aktuellen Verzeichnis. Dies kann beispielsweise
a1
eine normale Datei,a2
ein Verzeichnis odera3
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:
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: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:Wenn Sie das vergessen
..
:und es gibt zufällig genau zwei
.log
Dateien im aktuellen Verzeichnis, es wird erweitert auf:die wird umbenennen
one.log
und clobbertwo.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
Sie erhalten eine lange Liste aller Dateien, deren Name mit "" beginnta
, sowie der Inhalte aller Verzeichnisse, deren Name mit "" beginnta
. Wenn Sie nur eine Liste der Dateien und Verzeichnisse mit jeweils einer Zeile benötigen, können Sie Folgendes verwenden:was äquivalent ist zu:
Denken Sie erneut daran, dass der
ls
Befehl das*
Zeichen nie sieht .Wo dies dokumentiert ist,
man ls
zeigt Ihnen die Dokumentation für denls
Befehl auf nahezu jedem Unix-ähnlichen System. Auf den meisten Linux-basierten Systemen ist derls
Befehl Teil des GNU-Pakets coreutils. wenn Sie die habeninfo
Befehl, entwederinfo ls
oderinfo coreutils ls
sollten Sie mehr endgültige und umfassende Dokumentation geben. Andere Systeme, wie z. B. MacOS, verwenden möglicherweise andere Versionen desls
Befehls und verfügen möglicherweise nicht über deninfo
Befehl. Verwenden Sie für diese Systememan ls
. Undls --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 .
quelle
a*
die Liste aller Dateien im aktuellen Verzeichnis, deren Namen mit beginnena
.ls subdir/a*
echo
es. Wenn Sie also wissen möchten, was passiert, wenn Sie dies tunls a*
, führen Sie zuerstecho ls a*
echo a*
... die Schale tut glob Expansion sowiesoshopt -s failglob
verursacht das gleiche Verhalten. Das Festlegen von,nullglob
aber nicht,failglob
führt beispielsweise*nosuchfile*
dazu, dass eine leere Zeichenfolge angezeigt wird.Siehe Keith Thompsons Antwort; Aber um zu erklären, warum
ls --directory a*
Dateien und Verzeichnisse--directory
angezeigt werden : Die Option unterdrückt keine Nicht-Verzeichnisdateien. Stattdessen listet es die Verzeichnisse als solche auf, während es sonst deren Inhalt auflisten würde. Beispiel:quelle
-F
Um sehr deutlich zu sein, ist es in der Manualpage ls (1) dokumentiert :
-d, --directory listet Verzeichniseinträge anstelle von Inhalten auf und dereferenziert keine symbolischen Links
um fair zu sein, "Einträge statt Inhalte" könnten wahrscheinlich erklärender sein:
quelle
Globbing
Wie bereits erläutert, wird die Erweiterung von
*
(und ähnlichen Erweiterungen)glob
im Unix-Jargon als Bing bezeichnet und ist normalerweise eine Funktion des Befehlsprozessors (im Unix-Sprachgebrauch als "Shell" bekannt). Globbing kann also auch an vielen anderen Orten eingesetzt werden. Geben Sieman 7 glob
an der Shell einer klassischen Linux - Distribution (oder sehen diese ) , um mehr überglob
bing.Wurde in frühen Unix-
glob
Versionen von einem separaten Programm namens implementiert/etc/glob
( Dokumentation dazu finden Sie auf Seite 10 dieses alten UNIX-Handbuchs ). Heutzutage ist es eine Code-Routine, die von Code-Bibliotheken bereitgestellt wird und üblicherweise von Shells verwendet wird. Quelle : Wikipedia .Verzeichnisse
Warum werden sowohl
ls -d
Dateien als auch Verzeichnisse aufgelistet?Die
ls
Manpage erklärt, warum dies passiert, aber mit einer sehr knappen Erklärung. Also hier ist ein Versuch einer erweiterten Erklärung:Standardmäßig wird
ls
der Inhalt von Verzeichnissen aufgelistet, wenn ihr Name angegeben wird. Dies gilt auch für symbolische Verknüpfungen zu Verzeichnissen. Die-d
Option bedeutet, dass "wenn der Name (die Namen) des Verzeichnisses (der Verzeichnisse) angegeben wird" (was auch implizit durchglob
Bing angegeben werden kann) , nur die _Namen_s des Verzeichnisses (der Verzeichnisse) angezeigt werden, nicht jedoch deren Inhalt. Wenn Sie den oder die Namen von Symlinks zu Verzeichnissen (explizit oder implizit ) angeben , geben Sie den Dateinamen des Symlinks an , nicht den Inhalt des Verzeichnisses, auf das verwiesen wird.Die
-d
Option hat, soweit ich das beurteilen kann, nichts damit zu tun, welche Artikel aufgelistet sind; (: Quelle kann dies getan werden hier ) mitfind
, etwa so:find . -maxdepth 1 -type d
. Ich bin mir nicht sicher, ob es einen guten Weg gibt, dies nur mit GNU zu tunls
. Im Folgenden finden Sie einige Beispiele für die Verwendung desfind
Befehls.Fazit: Standardmäßig
ls
wird der Inhalt von Verzeichnissen angezeigt , wenn ihr Pfadname angegeben wird.-d
Ändert dieses Verhalten, indem nur der Verzeichnisname selbst angezeigt wird, wie dies bei einer Standarddatei der Fall wäre.quelle
Die Dokumentation gibt nicht an, dass nur Verzeichniseinträge aufgelistet werden, sondern dass beim
ls
Empfangen des Verzeichnisnamens der Verzeichniseintrag anstelle des Inhalts aufgeführt wird. Der beste Weg, dies zu verstehen, ist durch ein Beispiel:quelle
Die Dokumentation ist Teil der Shell . Insbesondere führt die Shell verschiedene Erweiterungen und Ersetzungen in einer bestimmten Reihenfolge durch, bevor ein Befehl ausgeführt wird.
Die Folge der Worterweiterungen für eine Bourne-kompatible Shell ist
Der
ls
Befehl sieht also nicht einmal die*
Zeichen, die Argumente sind bereits mit allen Dateien erweitert, die mit dema*
Glob-Muster übereinstimmen . Dies ist anders als unter Windows, wo jeder Befehl, der das Globbing von Dateinamen benötigt, diese Funktion selbst implementieren muss.quelle
Das Schlüsselwort, das Sie benötigen (
man bash
), ist "Pathname Expansion".quelle