Wer handelt (interpretiert) die * in
echo *
Kümmert sich das Echo um den Stern oder die Muschel und gibt eine Liste mit Dateinamen zurück?
Wie wäre es mit
cp temp temp*
Wer handelt (interpretiert) die * in
echo *
Kümmert sich das Echo um den Stern oder die Muschel und gibt eine Liste mit Dateinamen zurück?
Wie wäre es mit
cp temp temp*
Antworten:
bash (oder was auch immer Sie als Shell verwenden) ist das erste, was Sie lesen, und beginnt mit der Interpretation von Sonderzeichen wie ?
und *
. *
wird auf alle Übereinstimmungen in der CWD erweitert , was bedeutet, dass der Stern durch diese Übereinstimmungen ersetzt wird.
In den meisten Fällen ist dies recht unübersichtlich, kann jedoch von Zeit zu Zeit zu verwirrenden Fällen führen.
Folgendes berücksichtigen. Ein Verzeichnis hat diesen Inhalt:
Wenn du dann mv *
etwas scheinbar Seltsames eingibst, passiert: test3
ist da, aber der Rest ist weg. Obwohl es anfangs seltsam ist, macht es Sinn, wenn Sie erst einmal verstanden haben, an was die Bash tatsächlich geht mv
. Aufgrund des Sterns interpretiert Bash mv *
als mv test test1 test2 test3
und wenn MV diese Liste erhält, wird davon ausgegangen, dass das letzte Argument das Ziel ist, an das alle Dateien verschoben worden wären.
Wie für die Befehle, die Sie aufgelistet haben:
echo *
kann als ein Armenmann funktionieren ls
. Die Shell erweitert den Stern auf das, was sich in diesem Verzeichnis befindet, und gibt, wie Sie sicher bereits wissen, echo
buchstäblich alle Bashs aus, die ihr als Argumente übergeben wurden.cp temp temp*
verhält sich ähnlich wie der mv
oben beschriebene Befehl, es sei denn, es gibt nur ein Verzeichnis mit dem Namen temp. In diesem Fall sind Quell- und Zielname identisch, dh es wird nichts unternommen.*
statt ls
. Zum Beispiel for f in *; do
ist mehr zuverlässiger als for f in $(ls)
wenn ein Dateiname enthält Leerzeichen oder einen glob Charakter. (Es wird jedoch fehlschlagen, wenn sich keine Dateien im CWD befinden, sodass Sie diesen Fall überprüfen müssen.)
shopt nullglob
ist.
Wie bereits erwähnt, dehnt sich die Schale *
so echo
als Argumente , was auch immer die Shell finden im aktuellen Verzeichnis erhalten. Beachten Sie jedoch, dass, wenn die Erweiterung zu nichts führt, dh in diesem Fall, wenn das Verzeichnis keine nicht ausgeblendeten Dateien enthält, die *
unverändert bleiben und wie an den aufgerufenen Befehl übergeben werden (es sei denn, mit einigen Shells wie werden nicht standardmäßige Optionen verwendet bash
). echo *
wird sich dann nicht wie ein armer Mann verhalten, ls
da der erstere nichts druckt, während der letztere druckt *
.
Ebenso cp /tmp/temp temp*
wird eine Datei mit dem Namen temp*
im aktuellen Verzeichnis angelegt, wenn noch nicht mindestens eine Datei mit dem Namen beginnt temp
.
Wenn Sie möchten *
, dass die Übergabe in jedem Fall unverändert bleibt, können Sie sie mit einfachen Anführungszeichen '*'
, doppelten Anführungszeichen "*"
oder umgekehrten Schrägstrichen vor der Erweiterung schützen \*
.
In Bash befasst sich die Shell damit. Sie sehen das, wenn Sie es sogar *
ohne Echo versuchen
Auf der Grundlage einiger Kommentare würde ich bei der Ausführung von * ENTER vorschlagen, ein Verzeichnis zu erstellen und mit dem Befehl touch einige Dateien zu erstellen. Stellen Sie sicher, dass keine oder zumindest die erste alphabetisch nicht der Name ist eines Skripts oder Befehls im Pfad.
$ *
bash: a: command not found
$ echo *
a a.aa a.ab a.b a.htm a.tx
So ls *
ist ein bisschen ein Klischee
In Windows *
wird der Befehl verarbeitet, dir *.*
ist also kein Klischee.
Hinweis: Ich möchte hinzufügen, dass bei einigen Kommentaren das Risiko besteht, dass * und dann die EINGABETASTE ausgeführt werden. Wenn Sie eine Datei mit dem Namen rm haben, die sich zuerst in der Verzeichnisliste befindet, ist dies gefährlich, da alle darauf folgenden Dateien gelöscht würden. Auch und dies ist weniger unwahrscheinlich, wenn die erste Datei in der Verzeichnisliste der Name eines Skripts im Pfad ist, wird dieses ausgeführt.
rm
natürlich auch eine Datei mit dem Namen geben kann.
-rf
? Ich habe versucht , touch -rf
und , touch \-rf
aber es ist es nicht zu schaffen.
-rf
. (Ich verstehe die Gefahr einer Datei mit dem Namen rm und einer Datei mit dem Namen -rf und das Problem, * einzugeben und die Eingabetaste in einem wichtigen Ordner zu drücken, ich habe nicht vor, dies zu tun)
Die Shell führt mehrere Erweiterungen durch, bevor die Argumente an den Befehl übergeben werden.
Siehe auch https://www.gnu.org/software/bash/manual/bashref.html#Simple-Command-Expansion
Nicht bash-spezifisch, siehe http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_01