Pertama saya akan membuat basis tes - 5 file dan satu folder:
touch file1 file2 file3 file4 file5
mkdir folder
Selanjutnya saya akan menjalankan perintah tes. The -v
menspesifikasikan pilihan yang saya ingin setiap perintah mengeksekusi shell yang akan dicetak ke stderr
. The -x
pilihan menentukan bahwa saya menginginkan hal yang sama dicetak ke stderr
- tapi aku ingin itu dilakukan setelah perintah dievaluasi tapi sebelum shell berjalan itu.
sh -cxv 'echo mv *'
KELUARAN
echo mv *
+ echo mv file1 file2 file3 file4 file5 folder
mv file1 file2 file3 file4 file5 folder
Jadi Anda melihat bahwa perintah yang saya beri makan adalah shell echo mv *
dan perintah yang dijalankan oleh shell setelah *
diperluas echo mv
diikuti oleh semua file dan folder.
Secara default shell akan memperluas gumpalan seperti:
sh -cxv 'echo file[1-5]'
KELUARAN
echo file[1-5]
+ echo file1 file2 file3 file4 file5
file1 file2 file3 file4 file5
Ini adalah hasil dari set [+-]f
fungsi glob:
sh -cxvf 'echo file[1-5]'
KELUARAN
echo file[1-5]
+ echo 'file[1-5]'
file[1-5]
Jadi, ketika Anda menjalankan perintah di shell yang dikonfigurasi dengan opsi default seperti mv *
shell memperluas ke *
kata daftar argumen semua file di direktori saat ini diurutkan sesuai dengan lokal. Itu melakukan syscall exec(ve)
untuk mv
(pada dasarnya) dengan daftar argumen ini ditambahkan. Jadi mv
dapatkan semua argumen saat shell menggumpal dan mengurutkannya. Selain melakukan strace
untuk melihat efek ini, Anda dapat menggunakan debug lagi seperti:
sh -s -- mv * <<\SCRIPT
sed -n l /proc/$$/cmdline
echo "$@"
SCRIPT
KELUARAN
sh\000-s\000--\000mv\000file1\000file2\000file3\000file4\000file5\000folder\
\000$
mv file1 file2 file3 file4 file5 folder
Dan mudah dibawa:
( PS4= IFS=/; set -x mv *; : "/$*/" ) 2>&1
KELUARAN
: /mv/file1/file2/file3/file4/file5/folder/
Pada dasarnya, shell mengeksekusi mv
dengan isi direktori (jika tidak kosong dan tidak termasuk file / folder dengan nama yang dimulai dengan .
) sebagai daftar argumennya. mv
adalah POSIX ditentukan untuk menafsirkan argumen akhir sebagai direktori jika dipanggil dengan lebih dari dua argumen - dengan cara yang sama ln
adalah (karena, pada kenyataannya, mereka alat yang sangat serupa dalam mendasari fungsi) .
Cukup echo
es saja:
sh -cxv 'mv *' ; ls
KELUARAN
mv *
+ mv file1 file2 file3 file4 file5 folder
folder/
Semua file dipindahkan ke argumen akhir - karena itu adalah folder. Sekarang bagaimana jika itu bukan folder?
sh -cxv 'cd *; mv *'; ls . *
KELUARAN
cd *; mv *
+ cd folder
+ mv file1 file2 file3 file4 file5
mv: target ‘file5’ is not a directory
.:
folder/
folder:
file1 file2 file3 file4 file5
Beginilah cara POSIX menentukan mv
perilaku dalam kasus itu:
mv [-if] source_file target_file
mv [-if] source_file... target_dir
Dalam bentuk sinopsis pertama, mv
utilitas akan memindahkan file yang dinamai oleh operan source_file ke tujuan yang ditentukan oleh target_file . Bentuk sinopsis pertama ini diasumsikan ketika operan terakhir tidak menamai direktori yang ada dan bukan tautan simbolis yang merujuk ke direktori yang ada. Dalam hal ini, jika source_file menamai file non-direktori dan target_file diakhiri dengan /slash
karakter tambahan, mv
akan menganggap ini sebagai kesalahan dan tidak ada operan source_file yang akan diproses.
Dalam bentuk sinopsis kedua, mv
harus memindahkan setiap file yang dinamai oleh operan source_file ke file tujuan di direktori yang ada yang dinamai oleh operan target_dir , atau dirujuk jika target_dir adalah tautan simbolik yang merujuk ke direktori yang ada. Jalur tujuan untuk setiap source_file harus merupakan gabungan dari direktori target, /slash
karakter tunggal jika target tidak diakhiri dengan /slash
, dan komponen pathname terakhir dari source_file . Bentuk kedua ini diasumsikan ketika operan terakhir menamai direktori yang ada.
Jadi jika *
diperluas ke: