Bạn đang hiểu sai trang người đàn ông. Thứ nhất, phần --
báo hiệu kết thúc các tùy chọn không liên quan đến những gì bạn đang cố gắng thực hiện. Việc -c
ghi đè phần còn lại của dòng lệnh kể từ thời điểm đó, do đó nó không còn phải xử lý tùy chọn của bash nữa, nghĩa là nó --
sẽ được chuyển qua lệnh, không được xử lý bởi bash như là dấu kết thúc của tùy chọn.
Sai lầm thứ hai là các đối số bổ sung được gán làm tham số vị trí cho quy trình shell được khởi chạy, không được truyền dưới dạng đối số cho lệnh. Vì vậy, những gì bạn đang cố gắng có thể được thực hiện như một trong:
/bin/bash -c 'echo "$0" "$1"' foo bar
/bin/bash -c 'echo "$@"' bash foo bar
Trong trường hợp đầu tiên, truyền echo các tham số $0
và $1
rõ ràng, và trong trường hợp thứ hai, sử dụng "$@"
để mở rộng bình thường như "tất cả các tham số vị trí ngoại trừ $ 0". Lưu ý rằng trong trường hợp đó, chúng ta cũng phải vượt qua một cái gì đó để được sử dụng $0
; Tôi đã chọn "bash" vì đó là điều $0
bình thường, nhưng mọi thứ khác sẽ hoạt động.
Vì lý do nó được thực hiện theo cách này, thay vì chỉ truyền bất kỳ đối số nào bạn đưa trực tiếp vào lệnh bạn liệt kê: lưu ý rằng tài liệu nói "lệnh s được đọc từ chuỗi", số nhiều. Nói cách khác, sơ đồ này cho phép bạn thực hiện:
/bin/bash -c 'mkdir "$1"; cd "$1"; touch "$2"' bash dir file
Nhưng, lưu ý rằng cách tốt hơn để đáp ứng mục tiêu ban đầu của bạn có thể là sử dụng env
thay vì bash
:
/usr/bin/env -- "ls" "-l"
Nếu bạn không cần bất kỳ tính năng nào mà shell đang cung cấp, không có lý do gì để sử dụng nó - sử dụng env
trong trường hợp này sẽ nhanh hơn, đơn giản hơn và ít gõ hơn. Và bạn không cần phải suy nghĩ nhiều để đảm bảo rằng nó sẽ xử lý một cách an toàn tên tệp có chứa siêu ký tự vỏ hoặc khoảng trắng.