Ich kenne den Befehl ls
listet alle Verzeichnisse auf. Aber was bedeutet das ls *
Befehl tun? Ich habe es benutzt und es listet nur die Verzeichnisse auf. Steht der Stern vor ls
meine, wie tief werden die Verzeichnisse aufgelistet?
Akzeptierte Antwort:
ls
listet die Dateien und den Inhalt der Verzeichnisse auf, die als Argumente übergeben werden, und wenn kein Argument angegeben wird, listet es das aktuelle Verzeichnis auf. Es können auch eine Reihe von Optionen übergeben werden, die sein Verhalten beeinflussen (siehe man ls
für Einzelheiten).
Wenn ls
wird ein Argument namens *
übergeben , wird nach einer Datei oder einem Verzeichnis namens *
gesucht im aktuellen Verzeichnis und führen Sie es wie jedes andere auf. ls
behandelt den *
nicht Zeichen anders als alle anderen.
Wenn jedoch ls *
ist eine Hülle Kommandozeile, das ist Code in der Sprache einer Unix-Shell , dann erweitert die Shell diesen *
nach seinem Globing (auch als Dateinamengenerierung bezeichnet oder Dateiname/Pfadnamenerweiterung ) Regeln.
Während verschiedene Shells unterschiedliche Globbing-Operatoren unterstützen, einigen sich die meisten auf den einfachsten *
. *
als Muster bedeutet eine beliebige Anzahl von Zeichen, also *
als glob
wird auf die Liste der Dateien in den aktuellen Verzeichnissen erweitert, die diesem Muster entsprechen. Es gibt jedoch eine Ausnahme, bei der ein führender Punkt (.
) Zeichen in einem Dateinamen muss explizit abgeglichen werden, also *
erweitert sich tatsächlich auf die Liste der Dateien und Verzeichnisse, die nicht mit .
beginnen (in lexikalischer Reihenfolge).
Zum Beispiel, wenn das aktuelle Verzeichnis die Dateien namens .
enthält , ..
, .foo
, -l
und foo bar
, *
wird von der Shell auf zwei Argumente erweitert, die an ls
übergeben werden :-l
und foo bar
, also wird es so sein, als hätten Sie Folgendes eingegeben:
ls -l "foo bar"
oder
'ls' "-l" foo bar
Das sind drei Möglichkeiten, genau denselben Befehl auszuführen. In allen 3 Fällen ist die ls
Befehl (der wahrscheinlich von /bin/ls
ausgeführt wird aus einer Suche nach Verzeichnissen, die in $PATH
erwähnt werden ) werden diese 3 Argumente übergeben:„ls“, „-l“ und „foo bar“.
In diesem Fall übrigens ls
behandelt die erste (genau genommen zweite ) eine als Option.
Nun, wie gesagt, verschiedene Shells haben unterschiedliche Globbing-Operatoren. Vor ein paar Jahrzehnten, zsh
führte den **/
ein -Operator¹, was bedeutet, eine beliebige Ebene von Unterverzeichnissen abzugleichen, kurz für (*/)#
und ***/
das ist dasselbe, außer dass es symbolischen Links folgt, während es die Verzeichnisse absteigt.
Vor einigen Jahren (Juli 2003, ksh93o+
), ksh93
entschied sich, dieses Verhalten zu kopieren, entschied sich jedoch dafür, es optional zu machen, und deckte nur den **
ab Fall (nicht ***
). Auch während **
allein war in zsh
nichts Besonderes ² (bedeutete nur dasselbe wie *
wie in anderen traditionellen Shells seit **
bedeutet eine beliebige Anzahl von Zeichen gefolgt von einer beliebigen Anzahl von Zeichen), in ksh93 **
bedeutet dasselbe wie **/*
(also jede Datei oder jedes Verzeichnis unterhalb des aktuellen (außer versteckte Dateien)³.
bash
ksh93
kopiert ein paar Jahre später (Februar 2009, bash 4.0), mit der gleichen Syntax, aber einem unglücklichen Unterschied:bashs **
war wie zsh
ist ***
, das heißt, es folgte symbolischen Links, wenn es in Unterverzeichnisse zurückkehrte, was im Allgemeinen nicht das ist, was Sie wollen, und kann unangenehme Nebenwirkungen haben. Es wurde in bash-4.3 teilweise behoben, da Symlinks immer noch verfolgt wurden, aber die Rekursion dort aufhörte. Es wurde in 5.0 vollständig behoben.
yash
**
hinzugefügt in Version 2.0 im Jahr 2008, aktiviert mit dem extended-glob
Möglichkeit. Seine Implementierung ist näher an zsh
ist in diesem **
allein ist nichts besonderes. In Version 2.15 (2009) wurde ***
hinzugefügt wie in zsh
und zwei eigene Erweiterungen:.**
und .***
um versteckte Verzeichnisse bei der Rekursion einzuschließen (in zsh
, das D
Glob-Qualifizierer (wie in **/*(D)
) berücksichtigt versteckte Dateien und Verzeichnisse, aber wenn Sie nur versteckte Verzeichnisse durchlaufen, aber keine versteckten Dateien erweitern möchten, benötigen Sie ((*|.*)/)#*
oder **/[^.]*(D)
).
Die Fischschale unterstützt auch **
. Wie frühere Versionen von bash
, folgt es symbolischen Links, wenn es den Verzeichnisbaum absteigt. In dieser Shell jedoch **/*
ist nicht dasselbe wie **
. **
ist eher eine Erweiterung von *
die sich über mehrere Verzeichnisse erstrecken kann. In fish
, **/*.c
entspricht a/b/c.c
aber nicht a.c
, während a**.c
entspricht a.c
und ab/c/d.c
und zsh
ist **/.*
zum Beispiel muss .* **/.*
geschrieben werden . Dort ***
wird als **
verstanden gefolgt von *
also dasselbe wie **
.
tcsh
hat auch einen globstar
hinzugefügt Option in V6.17.01 (Mai 2010) und unterstützt sowohl **
und ***
à la zsh
.
Also in tcsh
, bash
und ksh93
, (wenn die entsprechende Option aktiviert ist (globstar
)) oder fish
, **
erweitert alle Dateien und Verzeichnisse unterhalb des aktuellen und ***
ist dasselbe wie **
für fish
, ein symbolischer Link, der **
durchläuft für tcsh
mit globstar
, und dasselbe wie *
in bash
und ksh93
(obwohl es nicht unmöglich ist, dass zukünftige Versionen dieser Shells auch Symlinks durchlaufen).
Oben haben Sie bemerkt, dass Sie sicherstellen müssen, dass keine der Erweiterungen als Option interpretiert wird. Dafür würden Sie Folgendes tun:
ls -- *
Oder:
ls ./*
Es gibt einige Befehle (es spielt keine Rolle für ls
), wobei die zweite vorzuziehen ist, da sogar mit dem --
Einige Dateinamen werden möglicherweise speziell behandelt. Dies ist der Fall bei -
für die meisten Textprogramme cd
und pushd
und Dateinamen, die den =
enthalten Zeichen für awk
zum Beispiel. ./
voranstellen allen Argumenten ihre besondere Bedeutung entzieht (zumindest für die oben genannten Fälle).
Es sollte auch beachtet werden, dass die meisten Shells eine Reihe von Optionen haben, die das Globbing-Verhalten beeinflussen (z. B. ob Punktdateien ignoriert werden oder nicht, die Sortierreihenfolge, was zu tun ist, wenn es keine Übereinstimmung gibt ...), siehe auch $FIGNORE
Parameter in ksh
Auch in jeder Shell außer csh
, tcsh
, fish
und zsh
, wenn das Globing-Muster mit keiner Datei übereinstimmt, wird das Muster als nicht erweitertes Argument übergeben, was zu Verwirrung und möglicherweise zu Fehlern führt. Zum Beispiel, wenn es im aktuellen Verzeichnis keine nicht versteckte Datei gibt
ls *
Wird tatsächlich ls
aufrufen mit den beiden Argumenten ls
und *
. Und da es überhaupt keine Datei gibt, heißt auch keine *
entweder sehen Sie eine Fehlermeldung von ls (nicht die Shell) wie:ls: cannot access *: No such file or directory
, was dafür bekannt ist, Leute denken zu lassen, dass es ls
war das war eigentlich das Erweitern der Globs.
Das Problem ist noch schlimmer in Fällen wie:
rm -- *.[ab]
Wenn *.a
nicht vorhanden ist noch *.b
Datei im aktuellen Verzeichnis, dann könnten Sie am Ende eine Datei namens *.[ab]
löschen versehentlich (csh
, tcsh
und zsh
würde ein keine Übereinstimmung melden Fehler und würde rm
nicht aufrufen (und fish
unterstützt nicht den [...]
Platzhalter)).
Wenn Sie einen wörtlichen *
übergeben möchten zu ls
, müssen Sie diesen *
zitieren Zeichen wie in ls *
oder ls '*'
oder ls "*"
. In POSIX-ähnlichen Shells kann Globbing mit set -o noglob
vollständig deaktiviert werden oder set -f
(letzteres funktioniert nicht in zsh
außer in sh
/ksh
Emulation).
.