Antworten:
ls
Listet die Dateien und den Inhalt der Verzeichnisse, die als Argumente übergeben werden, auf. Wenn kein Argument angegeben wird, wird das aktuelle Verzeichnis aufgelistet. Es können auch eine Reihe von Optionen übergeben werden, die sich auf das Verhalten auswirken ( man ls
Details siehe ).
Wenn ls
ein Argument mit dem Namen übergeben *
wird, sucht es *
im aktuellen Verzeichnis nach einer Datei oder einem Verzeichnis mit dem Namen und listet es wie jedes andere auf. ls
behandelt den *
Charakter nicht anders als irgendeinen anderen.
Wenn ls *
es sich jedoch um eine Shell- Befehlszeile handelt, wird die Shell *
entsprechend den Globbing- Regeln der entsprechenden Shell (auch als Dateinamengenerierung oder Dateinamenerweiterung bezeichnet ) erweitert.
Während verschiedene Shells verschiedene Globbing-Operatoren unterstützen, stimmen die meisten mit dem einfachsten überein *
. *
als Muster bedeutet , eine beliebige Anzahl von Zeichen, so *
wie ein glob
in der Liste der Dateien in den aktuellen Verzeichnissen zu erweitern, die dieses Muster passen. Es gibt jedoch eine Ausnahme, dass ein führendes Punkt ( .
) in einem Dateinamen explizit abgeglichen werden muss, sodass *
die Liste der Dateien und Verzeichnisse, die nicht mit .
(in lexikografischer Reihenfolge) beginnen, erweitert wird.
Zum Beispiel, wenn das aktuelle Verzeichnis die Dateien mit dem Namen enthält .
, ..
, .foo
, -l
und foo bar
, *
wird von der Shell auf zwei Argumente erweitert werden , um zu übergeben ls
: -l
und foo bar
, so es wie sein wird , wenn Sie eingegeben haben:
ls -l "foo bar"
oder
'ls' "-l" foo\ bar
Mit diesen drei Methoden können Sie genau den gleichen Befehl ausführen. In allen drei Fällen werden dem ls
Befehl (der wahrscheinlich /bin/ls
von einem Verzeichnis aus ausgeführt wird, in dem nachgeschlagen wird $PATH
) diese drei Argumente übergeben: "ls", "-l" und "foo bar".
Im Übrigen wird in diesem Fall ls
der erste (genau genommen der zweite ) als Option behandelt.
Wie ich bereits sagte, haben verschiedene Shells unterschiedliche Globbing-Operatoren. Vor einigen Jahrzehnten wurde zsh
der **/
Operator¹ eingeführt , der bedeutet, dass er mit jeder Ebene von Unterverzeichnissen übereinstimmt, kurz für (*/)#
und ***/
mit der Ausnahme, dass er Symlinks folgt, während er die Verzeichnisse absteigt.
Vor ein paar Jahren (Juli 2003 ksh93o+
) ksh93
entschied man sich, dieses Verhalten zu kopieren, entschied sich jedoch dafür, es optional zu machen, und deckte nur den **
Fall ab (nicht ***
). Auch während **
alleine nichts Besonderes war zsh
(nur dasselbe gemeint *
wie in anderen traditionellen Shells, da **
bedeutet, dass eine beliebige Anzahl von Zeichen gefolgt von einer beliebigen Anzahl von Zeichen), **
bedeutete ksh93 dasselbe wie **/*
(also jede Datei oder jedes Verzeichnis unterhalb der aktuellen) (ausgenommen versteckte Dateien).
bash
ksh93
Einige Jahre später kopiert (Februar 2009, Bash 4.0), mit der gleichen Syntax, aber mit einem unglücklichen Unterschied: Bash **
war wie zsh
's ***
, dh es folgten Symlinks, wenn Sie in Unterverzeichnisse zurückkehren, was im Allgemeinen nicht das ist, was Sie wollen und tun kann böse Nebenwirkungen haben. Es wurde teilweise in Bash-4.3 behoben, dass Symlinks weiterhin 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 der extended-glob
Option. Seine Implementierung ist näher zsh
dran, das **
allein ist nichts Besonderes. In Version 2.15 (2009) wurden ***
like in zsh
und zwei eigene Erweiterungen hinzugefügt : .**
und .***
um verborgene Verzeichnisse bei der Rekursion einzuschließen ( in ), berücksichtigt zsh
das D
Qualifikationsmerkmal glob (wie in **/*(D)
) verborgene Dateien und Verzeichnisse, wenn Sie jedoch nur verborgene Verzeichnisse durchlaufen möchten Verzeichnisse, aber versteckte Dateien nicht erweitern, benötigen Sie ((*|.*)/)#*
oder **/[^.]*(D)
).
Die Fischschale unterstützt auch **
. Wie in früheren Versionen von bash
folgt es Symlinks beim Abstieg in den Verzeichnisbaum. In dieser Shell ist jedoch **/*
nicht das gleiche wie **
. **
ist eher eine Erweiterung *
, die sich über mehrere Verzeichnisse erstrecken kann. In fish
, **/*.c
wird passen , a/b/c.c
aber nicht a.c
, während a**.c
passt auf a.c
und ab/c/d.c
und zsh
ist **/.*
zum Beispiel hat geschrieben werden .* **/.*
. Dort ***
wird verstanden wie **
gefolgt von *
so dasselbe wie **
.
tcsh
fügte auch eine globstar
Option in V6.17.01 (Mai 2010) hinzu und unterstützt sowohl **
als auch ***
à la zsh
.
So in tcsh
, bash
und ksh93
, (wenn die entsprechende Option aktiviert ist ( globstar
)) oder fish
, **
erweitert um alle Dateien und Verzeichnisse unterhalb des aktuellen, und ***
ist die gleiche wie **
für fish
eine Symlink überquert **
für tcsh
mit globstar
, und das gleiche wie *
in bash
und ksh93
(obwohl es Es ist nicht unmöglich, dass zukünftige Versionen dieser Shells auch Symlinks durchlaufen werden.
Oben haben Sie die Notwendigkeit bemerkt, sicherzustellen, 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 ls
), bei denen der zweite vorzuziehen ist, da selbst bei --
einigen Dateinamen eine spezielle Behandlung möglich ist. Es ist der Fall -
für die meisten Texte Dienstprogramme, cd
und pushd
und Dateinamen , die die enthaltenen =
Zeichen für awk
zum Beispiel. Das Voranstellen ./
aller Argumente beseitigt ihre besondere Bedeutung (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 keine Übereinstimmung vorliegt ...), siehe auch den $FIGNORE
Parameter inksh
Auch in jeder Schale aber csh
, tcsh
, fish
und zsh
, wenn das Globbing Muster keine Datei übereinstimmt, wird das Muster als nicht expandierten Argument übergeben , die Verwirrung und möglicherweise Fehler verursacht. Zum Beispiel, wenn sich im aktuellen Verzeichnis keine nicht ausgeblendete Datei befindet
ls *
Werde eigentlich ls
mit den beiden Argumenten ls
und anrufen *
. Und da es überhaupt keine Datei ist, so dass keiner genannt *
entweder, erhalten Sie eine Fehlermeldung aus sehen ls (nicht die Shell) wie: ls: cannot access *: No such file or directory
, die bekannt ist Menschen zu denken , dass es war , ls
dass tatsächlich wurde die Kleckse zu erweitern.
Das Problem ist noch schlimmer in Fällen wie:
rm -- *.[ab]
Wenn es keine gibt , *.a
noch *.b
im aktuellen Verzeichnis - Datei, dann könnten Sie eine Datei namens Löschen am Ende *.[ab]
versehentlich ( csh
, tcsh
und zsh
würde einen Bericht keine Übereinstimmung Fehler und würde nicht nennen rm
(und fish
unterstützt nicht die [...]
Platzhalter)).
Wenn Sie eine wörtliche passieren wollen *
zu ls
, haben Sie das zitieren *
Charakter in irgendeiner Weise wie in ls \*
oder ls '*'
oder ls "*"
. In POSIX-ähnlichen Shells kann das Globbing mit set -o noglob
oder deaktiviert werden set -f
(letzteres funktioniert nur zsh
in sh
/ ksh
emulation).
¹ Während (*/)#
es immer unterstützt wurde, war es zuerst wie ..../
in zsh-2.0 (und möglicherweise vorher), dann ****/
in 2.1, bevor es seine endgültige Form **/
in 2.2 bekam (Anfang 1992).
find -name *
. Insbesondere bei komplexeren Mustern werden die Benutzer häufig nicht bemerken, dass genau eine Übereinstimmung im aktuellen Verzeichnis vorliegt, an die sie den Stern nicht weitergeben find
.
*.[ab]
würde versucht, alles zu löschen, was mit endet .[ab]
. [
ist nichts Besonderes in Fisch.
Der Befehl ls
lautet standardmäßig ls .
: Alle Einträge im aktuellen Verzeichnis auflisten .
Der Befehl ls *
bedeutet 'ls auf die Erweiterung des *
Shell-Musters ausführen '
Das *
Muster wird von der Shell verarbeitet und auf alle Einträge im aktuellen Verzeichnis erweitert, mit Ausnahme der Einträge, die mit einem beginnen .
. Es wird eine Ebene tiefer gehen.
Die Interpretation von Doppel- oder Dreifachmustern *
hängt von der tatsächlich verwendeten Schale ab.
*
ist ein Platzhalter, der 0 oder mehr Zeichen entspricht. Einige moderne Shells werden beim Anzeigen des **
Musters wieder in Unterverzeichnisse verschoben .
*
Sie etwas hinzufügen müssen, finden Sie in der anderen Antwort eine Erklärung für den Globstar. Es sollte auch klargestellt werden, dass ls nichts mit den Sternchen zu tun hat, es hat keines dieser Sternchen bestanden. Führen echo ls *
Sie den Befehl aus, um zu sehen, was beim Schreiben ausgeführt wird ls *
.
Sie können den gesamten Prozess entmystifizieren, indem Sie echo
statt ls
zuerst Folgendes eingeben , um zu sehen, zu was der Befehl erweitert wird:
$ echo *
Applications Downloads Documents tmp.html
Also in diesem Fall ls *
erweitertls Applications Downloads Documents tmp.html
$ echo **
Applications Downloads Documents tmp.html
$ echo ***
Applications Downloads Documents tmp.html
Also keine Veränderung. Dies setzt voraus, dass Sie bash
als Shell verwenden - die meisten Menschen sind es und verschiedene Shells haben ein unterschiedliches Verhalten. Wenn Sie ash
oder csh
oder ksh
oder verwenden zsh
, können Sie davon ausgehen, dass die Dinge anders funktionieren. Das ist der Punkt, wenn man verschiedene Muscheln hat.
Versuchen bash
wir also etwas anderes (immer noch mit ), damit wir eine Vorstellung davon bekommen, was der globbing ( *
) -Operator für uns tun kann. Zum Beispiel können wir nach einem Teil des Namens filtern:
$ echo D*
Downloads Documents
Interessanterweise ist ein abschließender Schrägstrich ein impliziter Bestandteil jedes Verzeichnisnamens. So */
ergeben sich nur die Verzeichnisse (und symbolische Links zu Verzeichnissen):
$ echo */
Applications/ Downloads/ Documents/
Und wir können auf mehreren Ebenen filtern, indem wir Schrägstriche in die Mitte setzen:
$ echo D*/*/
Documents/Work/ /Documents/unfinished/
Da das Downloads
Verzeichnis keine Unterverzeichnisse enthält, wird es nicht in der Ausgabe ausgegeben. Dies ist sehr nützlich, um nur die gewünschten Dateien zu untersuchen. Ich benutze immer solche Befehle:
$ ls -l /home/*/public_html/wp-config.php
Hier werden, falls vorhanden, alle wp-config.php
Dateien aufgelistet, die auf der Basisebene eines Benutzerverzeichnisses vorhanden sind public_html
. Oder vielleicht um vollständiger zu sein:
$ find /home/*/public_html/ -name wp-config.php
Auf diese Weise werden alle wp-config.php
Dateien in den public_html
Verzeichnissen eines Benutzers oder in einem seiner Unterverzeichnisse gefunden. Sie werden jedoch effizienter ausgeführt, als nur, find /home/ -name wp-config.php
weil nur die public_html
Verzeichnisse der einzelnen Benutzer überprüft werden.
bash
als Shell verwenden" ← und dass der Globstar nicht aktiviert ist. shopt -s globstar
und versuchen Sie es erneut ...
set -x
, den "tatsächlichen" Befehl zu drucken, der jedes Mal ausgeführt wird (Ausschalten mit set +x
).
In einigen Shells, einschließlich Bash 4.x mit globstar
aktivierter Option, **
wird ein rekursiver Glob ausgeführt, der absteigende übereinstimmende Verzeichnisse enthält. Zusätzliche Sternchen ändern diesen Vorgang nicht weiter.
ksh93
und zsh
, bash
tut Traverse Symlinks in der Rekursion , die im allgemeinen unerwünscht ist.
Wenn Sie tief tauchen möchten, verwenden Sie die Option ls -R (rekursiv) oder verwenden Sie find wie folgt:
find . -ls
"find" taucht bis zum Ende des Verzeichnisbaums auf (wie auch "ls -R") und bietet viele weitere Optionen, z. B. das Auflisten von Verzeichnissen (-type d), nur Dateien (-type f) oder das Anzeigen von Dateien mit anderen Merkmale (kein Benutzer in / etc / passwd, bestimmte Berechtigungen und vieles mehr). "find" ist auch etwas sicherer bei der Skripterstellung (aufgrund inkonsistenter Globbing-Regeln zwischen Shells sowie spezieller Escapes für Dateien mit Bindestrichen usw.).
Shell-Platzhalter-Globbing funktioniert bei Punktdateien nicht nur mit einem Sternchen '*'. Um nur Punktedateien aufzulisten, verwenden Sie:
ls .??*
Extra * fügt keine Tiefenstufe hinzu. Aber wenn du es versuchst
ls */*/*
- Sie erhalten eine Liste der Unterordner von Unterordnern in Ordnern im aktuellen Ordner ...
*
s die Tiefe.
bash
mit der Globstar-Option, der Korn-Shell und zsh. Und vielleicht noch andere, würde ich raten. unix.stackexchange.com/a/62665/14831
Mein Hauptgriff ist, dass Echo ** / *. Ext im Allgemeinen ...
Mai oder Mai nicht: Listet eine .ext-Datei im aktuellen Verzeichnis auf
Mai oder Mai nicht:. *. Ext-Dateien einschließen
Im Allgemeinen würde ich es vorziehen, wenn der Glob-Ausdruck '** /' ist und eine leere Zeichenfolge (kein Unterverzeichnis) ergibt. So konvertiere ich Glob-Ausdrücke in Programmeingaben. Natürlich versichere ich, dass es Kommentare gibt, die dies in Anwendungsbeispielen erklären.