Đầu tiên tôi sẽ tạo một cơ sở thử nghiệm - 5 tệp và một thư mục:
touch file1 file2 file3 file4 file5
mkdir folder
Tiếp theo tôi sẽ chạy một lệnh kiểm tra. Các -vquy định cụ thể tùy chọn mà tôi muốn mọi mệnh lệnh thực thi shell được in tới stderr. Các -xquy định cụ thể tùy chọn mà tôi muốn cùng in để stderr- nhưng tôi muốn nó được thực hiện sau khi lệnh được đánh giá nhưng trước khi vỏ chạy nó.
sh -cxv 'echo mv *'
ĐẦU RA
echo mv *
+ echo mv file1 file2 file3 file4 file5 folder
mv file1 file2 file3 file4 file5 folder
Vì vậy, bạn thấy rằng lệnh tôi cung cấp shell là echo mv *và lệnh shell thực thi sau khi * được mở rộng được echo mvtheo sau bởi tất cả các tệp và thư mục.
Theo mặc định, vỏ sẽ mở rộng những đống như:
sh -cxv 'echo file[1-5]'
ĐẦU RA
echo file[1-5]
+ echo file1 file2 file3 file4 file5
file1 file2 file3 file4 file5
Đây là kết quả của set [+-]fchức năng toàn cầu:
sh -cxvf 'echo file[1-5]'
ĐẦU RA
echo file[1-5]
+ echo 'file[1-5]'
file[1-5]
Vì vậy, khi bạn chạy một lệnh trong shell được cấu hình với các tùy chọn mặc định như mv *shell sẽ mở rộng thành *từ một danh sách đối số của tất cả các tệp trong thư mục hiện tại được sắp xếp theo miền địa phương. Nó thực hiện các tòa nhà exec(ve)cho mv (về cơ bản) với danh sách đối số này được nối thêm. Vì vậy, mvcó được tất cả các đối số như cái vỏ làm cho họ hả hê và sắp xếp chúng. Bên cạnh việc thực hiện straceđể xem các hiệu ứng này, bạn có thể sử dụng gỡ lỗi một lần nữa như:
sh -s -- mv * <<\SCRIPT
sed -n l /proc/$$/cmdline
echo "$@"
SCRIPT
ĐẦU RA
sh\000-s\000--\000mv\000file1\000file2\000file3\000file4\000file5\000folder\
\000$
mv file1 file2 file3 file4 file5 folder
Và di chuyển:
( PS4= IFS=/; set -x mv *; : "/$*/" ) 2>&1
ĐẦU RA
: /mv/file1/file2/file3/file4/file5/folder/
Về cơ bản, shell thực thi mvvới nội dung của thư mục (nếu nó không trống và không bao gồm các tệp / thư mục có tên bắt đầu bằng .) làm danh sách đối số của nó. mvlà POSIX quy định để giải thích lập luận cuối cùng của nó như một thư mục nếu nó được gọi với hơn hai đối số - theo cách tương tự lnlà (bởi vì, trên thực tế, họ đang công cụ cực kỳ tương tự chức năng cơ bản) .
Đủ echoes mặc dù:
sh -cxv 'mv *' ; ls
ĐẦU RA
mv *
+ mv file1 file2 file3 file4 file5 folder
folder/
Tất cả các tệp đã được chuyển vào đối số cuối cùng - bởi vì đó là một thư mục. Bây giờ nếu nó không phải là một thư mục thì sao?
sh -cxv 'cd *; mv *'; ls . *
ĐẦU RA
cd *; mv *
+ cd folder
+ mv file1 file2 file3 file4 file5
mv: target ‘file5’ is not a directory
.:
folder/
folder:
file1 file2 file3 file4 file5
Đây là cách POSIX chỉ định mv nên hành xử trong trường hợp đó:
mv [-if] source_file target_file
mv [-if] source_file... target_dir
Trong biểu mẫu tóm tắt đầu tiên, mvtiện ích sẽ di chuyển tệp được đặt tên bởi toán hạng source_file đến đích được chỉ định bởi target_file . Biểu mẫu tóm tắt đầu tiên này được giả sử khi toán hạng cuối cùng không đặt tên thư mục hiện có và không phải là một liên kết tượng trưng đề cập đến một thư mục hiện có. Trong trường hợp này, nếu source_file đặt tên tệp không phải là thư mục và target_file kết thúc bằng /slashký tự dấu , mvsẽ coi đây là lỗi và sẽ không có toán hạng source_file nào được xử lý.
Trong biểu mẫu tóm tắt thứ hai, mvsẽ di chuyển từng tệp được đặt tên bởi toán hạng source_file sang tệp đích trong thư mục hiện có được đặt tên bởi toán hạng target_dir hoặc được tham chiếu nếu target_dir là liên kết tượng trưng liên quan đến thư mục hiện có. Đường dẫn đích cho mỗi source_file sẽ là nối của thư mục đích, một /slashký tự nếu mục tiêu không kết thúc bằng a /slashvà thành phần tên đường dẫn cuối cùng của source_file . Dạng thứ hai này được giả sử khi toán hạng cuối cùng đặt tên cho một thư mục hiện có.
Vì vậy, nếu *mở rộng đến: