Đầ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 -v
quy đị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 -x
quy đị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 mv
theo 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 [+-]f
chứ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, mv
có đượ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 mv
vớ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ó. mv
là 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ự ln
là (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) .
Đủ echo
es 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, mv
tiệ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 /slash
ký tự dấu , mv
sẽ 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, mv
sẽ 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 /slash
ký tự nếu mục tiêu không kết thúc bằng a /slash
và 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: