Najpierw stworzę bazę testową - 5 plików i jeden folder:
touch file1 file2 file3 file4 file5
mkdir folder
Następnie uruchomię polecenie testowe. Ta -v
opcja określa, że chcę, aby każde polecenie wykonywane przez powłokę było drukowane stderr
. Ta -x
opcja określa, że chcę to samo wydrukować stderr
- ale chcę, aby zrobiono to po ocenie polecenia, ale przed uruchomieniem go przez powłokę.
sh -cxv 'echo mv *'
WYDAJNOŚĆ
echo mv *
+ echo mv file1 file2 file3 file4 file5 folder
mv file1 file2 file3 file4 file5 folder
Widzicie więc, że po poleceniu, które karmię powłokę, echo mv *
po poleceniu, które wykonuje powłoka po *
rozwinięciu, echo mv
następują wszystkie pliki i folder.
Domyślnie powłoka rozwija globusy, takie jak:
sh -cxv 'echo file[1-5]'
WYDAJNOŚĆ
echo file[1-5]
+ echo file1 file2 file3 file4 file5
file1 file2 file3 file4 file5
Wynika to z set [+-]f
funkcji glob:
sh -cxvf 'echo file[1-5]'
WYDAJNOŚĆ
echo file[1-5]
+ echo 'file[1-5]'
file[1-5]
Kiedy więc uruchomisz polecenie w powłoce skonfigurowanej z domyślnymi opcjami, takimi jak mv *
powłoka, rozwija się do *
słowa lista argumentów wszystkich plików w bieżącym katalogu posortowana według ustawień regionalnych. Wykonuje syscall exec(ve)
dla mv
(zasadniczo) z dołączoną listą argumentów. mv
Otrzymuje więc wszystkie argumenty, gdy powłoka je globalizuje i sortuje. Oprócz robienia strace
tych efektów, możesz ponownie użyć debugowania w następujący sposób:
sh -s -- mv * <<\SCRIPT
sed -n l /proc/$$/cmdline
echo "$@"
SCRIPT
WYDAJNOŚĆ
sh\000-s\000--\000mv\000file1\000file2\000file3\000file4\000file5\000folder\
\000$
mv file1 file2 file3 file4 file5 folder
I przenośnie:
( PS4= IFS=/; set -x mv *; : "/$*/" ) 2>&1
WYDAJNOŚĆ
: /mv/file1/file2/file3/file4/file5/folder/
Zasadniczo powłoka jest wykonywana mv
z zawartością katalogu (jeśli nie jest pusty i nie zawiera plików / folderów o nazwach rozpoczynających się od .
) jako listy argumentów. mv
POSIX jest określony interpretować jako ostatecznego argumentu katalogu, jeśli jest ona wywoływana z więcej niż dwóch argumentów - w ten sam sposób ln
jest (bo w rzeczywistości są one bardzo podobne narzędzia w funkcji bazowych) .
Wystarczająco dużo echo
:
sh -cxv 'mv *' ; ls
WYDAJNOŚĆ
mv *
+ mv file1 file2 file3 file4 file5 folder
folder/
Wszystkie pliki zostały przeniesione do ostatniego argumentu - ponieważ jest to folder. Co teraz, jeśli nie jest to folder?
sh -cxv 'cd *; mv *'; ls . *
WYDAJNOŚĆ
cd *; mv *
+ cd folder
+ mv file1 file2 file3 file4 file5
mv: target ‘file5’ is not a directory
.:
folder/
folder:
file1 file2 file3 file4 file5
Tak określa POSIX mv
w takim przypadku:
mv [-if] source_file target_file
mv [-if] source_file... target_dir
W pierwszej formie streszczenia mv
narzędzie przenosi plik nazwany przez operand plik_źródłowy do miejsca docelowego określonego przez plik_cel . Ten pierwszy formularz streszczenia zakłada się, gdy ostatni operand nie nazywa istniejącego katalogu i nie jest dowiązaniem symbolicznym odnoszącym się do istniejącego katalogu. W tym przypadku, jeśli plik_zrodlowy nazwy pliku non-katalog i target_file kończy wleczonego /slash
charakterem, mv
traktuje to jako błąd i nie ma plik_zrodlowy argumenty będą przetwarzane.
W drugim formularzu streszczenia mv
przenosi każdy plik nazwany operandem pliku źródłowego do pliku docelowego w istniejącym katalogu nazwanym przez operand katalog_docelowy lub do którego odwołuje się, jeśli katalog_docelowy jest dowiązaniem symbolicznym do istniejącego katalogu. Ścieżką docelową dla każdego pliku_źródłowego jest konkatenacja katalogu docelowego, pojedynczy /slash
znak, jeśli cel nie kończy się na /slash
, oraz ostatni składnik nazwy pliku źródłowego . Ta druga forma jest zakładana, gdy końcowy operand nazywa istniejący katalog.
Więc jeśli *
rozwija się do: