Zuerst mache ich eine Testbasis - 5 Dateien und einen Ordner:
touch file1 file2 file3 file4 file5
mkdir folder
Als nächstes führe ich einen Testbefehl aus. Die -v
Option gibt an, dass jeder Befehl, den die Shell ausführt, gedruckt werden soll stderr
. Die -x
Option gibt an, dass dasselbe gedruckt werden soll stderr
- dies soll jedoch erfolgen, nachdem der Befehl ausgewertet wurde, aber bevor die Shell ihn ausführt.
sh -cxv 'echo mv *'
AUSGABE
echo mv *
+ echo mv file1 file2 file3 file4 file5 folder
mv file1 file2 file3 file4 file5 folder
Sie sehen also, dass der Befehl, den ich der Shell übergebe, echo mv *
und der Befehl, den die Shell ausführt, nachdem sie *
erweitert wurde, echo mv
von all diesen Dateien und dem Ordner gefolgt wird.
Standardmäßig erweitert die Shell Globs wie folgt :
sh -cxv 'echo file[1-5]'
AUSGABE
echo file[1-5]
+ echo file1 file2 file3 file4 file5
file1 file2 file3 file4 file5
Dies ist ein Ergebnis der set [+-]f
Glob-Funktion:
sh -cxvf 'echo file[1-5]'
AUSGABE
echo file[1-5]
+ echo 'file[1-5]'
file[1-5]
Wenn Sie also einen Befehl in einer Shell ausführen, die mit Standardoptionen wie mv *
der Shell konfiguriert ist, wird *
eine Argumentliste aller Dateien im aktuellen Verzeichnis in das Wort eingeblendet, sortiert nach Ländereinstellung. Es führt den Syscall exec(ve)
für mv
(im Wesentlichen) mit dieser angehängten Argumentliste aus. mv
Erhält also alle Argumente, während die Shell sie sortiert. Neben strace
diesen Effekten können Sie das Debug-Out wie folgt erneut verwenden:
sh -s -- mv * <<\SCRIPT
sed -n l /proc/$$/cmdline
echo "$@"
SCRIPT
AUSGABE
sh\000-s\000--\000mv\000file1\000file2\000file3\000file4\000file5\000folder\
\000$
mv file1 file2 file3 file4 file5 folder
Und portabel:
( PS4= IFS=/; set -x mv *; : "/$*/" ) 2>&1
AUSGABE
: /mv/file1/file2/file3/file4/file5/folder/
Grundsätzlich wird die Shell mv
mit dem Inhalt des Verzeichnisses (wenn es nicht leer ist und keine Dateien / Ordner enthält, deren Namen mit "" beginnen .
) als Argumentliste ausgeführt. mv
wird POSIX angegeben, um sein letztes Argument als Verzeichnis zu interpretieren, wenn es mit mehr als zwei Argumenten aufgerufen wird - auf dieselbe Weise ln
wie (weil es sich in der zugrunde liegenden Funktion tatsächlich um unglaublich ähnliche Tools handelt) .
Genug davon echo
:
sh -cxv 'mv *' ; ls
AUSGABE
mv *
+ mv file1 file2 file3 file4 file5 folder
folder/
Alle Dateien wurden in das letzte Argument verschoben, da es sich um einen Ordner handelt. Was ist nun, wenn es sich nicht um einen Ordner handelt?
sh -cxv 'cd *; mv *'; ls . *
AUSGABE
cd *; mv *
+ cd folder
+ mv file1 file2 file3 file4 file5
mv: target ‘file5’ is not a directory
.:
folder/
folder:
file1 file2 file3 file4 file5
So sollte sich POSIX mv
in diesem Fall verhalten:
mv [-if] source_file target_file
mv [-if] source_file... target_dir
In der ersten Synopse verschiebt das mv
Dienstprogramm die vom Operanden source_file angegebene Datei in das von target_file angegebene Ziel . Diese erste Zusammenfassungsform wird angenommen, wenn der letzte Operand kein vorhandenes Verzeichnis benennt und kein symbolischer Link ist, der auf ein vorhandenes Verzeichnis verweist. Wenn in diesem Fall Quellendateinamen einer Nicht-Verzeichnisdatei und Zieldatei mit einem nachgestellten /slash
Zeichen enden , mv
wird dies als Fehler behandelt, und es werden keine Quellendatei- Operanden verarbeitet.
mv
Verschiebt in der zweiten Zusammenfassungsform jede Datei, die von einem Quellendatei- Operanden benannt wurde, in eine Zieldatei im vorhandenen Verzeichnis, das vom Operanden Zielverzeichnis benannt wurde , oder verweist darauf, wenn Zielverzeichnis eine symbolische Verknüpfung ist, die auf ein vorhandenes Verzeichnis verweist. Der Zielpfad für jede Quellendatei besteht aus der Verkettung des Zielverzeichnisses, einem einzelnen /slash
Zeichen, wenn das Ziel nicht auf a endete /slash
, und der letzten Pfadname-Komponente der Quellendatei . Diese zweite Form wird angenommen, wenn der letzte Operand ein vorhandenes Verzeichnis benennt.
Also, wenn *
erweitert um: