Tại sao `watch` tạo` ls / tmp` liệt kê nội dung của $ HOME?


13

Tôi đang cố gắng xem số lượng tập tin trong /tmp/thư mục của tôi . Đối với điều này, tôi nghĩ rằng lệnh này sẽ làm việc:

watch sh -c 'ls /tmp/|wc -l'

Nhưng nó dường như hoạt động như thể lskhông có đối số. Cụ thể, tôi đang ở ~và tôi nhận được số lượng tệp ở đó thay vì /tmp/. Tôi tìm thấy một cách giải quyết, có vẻ như hoạt động:

watch sh -c 'ls\ /tmp/|wc -l'

Nhưng tại sao tôi cần phải thoát khỏi không gian giữa ls/tmp/? Làm thế nào là lệnh được chuyển đổi watchđể lsđầu ra được đưa vào wc, nhưng /tmp/không được chuyển làm đối số ls?


1
watch "sh -c 'ls /tmp | wc -l'"làm lệnh này sẽ nhận được ảnh hưởng mong muốn. Đây không phải là lỗi đồng hồ, hãy thử sh -c ls /tmpvà bạn sẽ nhận được thư mục nhà của mình (nhưng tôi không biết tại sao ...)
Jacob Minshall

8
Không phải là một câu trả lời nhưng bạn đang sử dụng watchkhông chính xác. Lệnh mà bạn chuyển đến watchlần lượt được cung cấp watchcho sh -c, vì vậy bạn có hiệu lực thực hiện sh -chai lần.
iruvar

Nếu bạn tò mò bạn cũng có thể xem qua nguồn .
michas

1
@JacobMinshall, tại sao lại đơn giản: /tmpĐó là một đối số sh, trong trường hợp đó, không phải là một đối số ls.
Charles Duffy

Câu trả lời:


17

Sự khác biệt có thể được nhìn thấy qua strace:

$ strace -ff -o bq watch sh -c 'ls\ /tmp/|wc -l'
^C
$ strace -ff -o nobq watch sh -c 'ls /tmp/|wc -l'
^C
$ grep exec bq* | grep sh
bq.29218:execve("/usr/bin/watch", ["watch", "sh", "-c", "ls\\ /tmp/|wc -l"], [/* 54 vars */]) = 0
bq.29219:execve("/bin/sh", ["sh", "-c", "sh -c ls\\ /tmp/|wc -l"], [/* 56 vars */]) = 0
bq.29220:execve("/bin/sh", ["sh", "-c", "ls /tmp/"], [/* 56 vars */]) = 0
$ grep exec nobq* | grep sh
nobq.29227:execve("/usr/bin/watch", ["watch", "sh", "-c", "ls /tmp/|wc -l"], [/* 54 vars */]) = 0
nobq.29228:execve("/bin/sh", ["sh", "-c", "sh -c ls /tmp/|wc -l"], [/* 56 vars */]) = 0
nobq.29229:execve("/bin/sh", ["sh", "-c", "ls", "/tmp/"], [/* 56 vars */]) = 0

Trong trường hợp backquote, ls /tmpđược truyền dưới dạng một đối số duy nhất cho -cđến sh, chạy như mong đợi. Nếu không có backquote này, lệnh thay vào đó là phân tách từ khi watchchạy shlần lượt chạy được cung cấp sh, do đó chỉ lsđược truyền dưới dạng đối số -c, có nghĩa là phụ con shsẽ chỉ chạy một lslệnh trần và liệt kê nội dung của hoạt động hiện tại danh mục.

Vậy, tại sao lại có biến chứng sh -c ...? Tại sao không đơn giản là chạy watch 'ls /tmp|wc -l'?


Oh thực sự, đã không nghĩ đến việc cố gắng với stracenó.
Ruslan

1
Trên thực tế, `là backquote (hoặc back-tick). Câu hỏi này là về \, đó là dấu gạch chéo ngược.
G-Man nói 'Phục hồi Monica'

@Ruslan: Tôi đã đăng bình luận này về câu trả lời này vì nó là một bình luận về câu trả lời này . thrig nói "Trong trường hợp backquote , ls /tmplà ..." và "Không có backquote này , lệnh là ...", và sử dụng bqnobqnhư tên tệp, khi tất cả trong khi đề cập đến dấu gạch chéo ngược trong ls\ /tmplệnh của bạn .
G-Man nói 'Phục hồi Monica'

8

Có hai loại watchlệnh chính (trong số các lệnh chạy lệnh định kỳ, watchkhông phải là lệnh chuẩn, thậm chí có những hệ thống watchthực hiện một số thứ hoàn toàn khác như rình mò trên một dòng tty khác trên FreeBSD).

Một đối tượng đã vượt qua sự kết hợp các đối số của nó với khoảng trắng vào một trình bao (nó thực hiện trong lệnh gọi hiệu ứng sh -c <concatenation-of-arguments>) và một đối tượng chỉ chạy lệnh được chỉ định với các đối số được chỉ định mà không cần gọi trình bao.

Bạn đang ở trong tình huống đầu tiên, vì vậy bạn chỉ cần:

watch 'ls /tmp/|wc -l'

Khi bạn làm:

watch sh -c 'ls /tmp/|wc -l'

bạn watchthực sự chạy:

sh -c 'sh -c ls /tmp/|wc -l'

sh -c ls /tmp/đang chạy các lskịch bản nội tuyến nơi $0được /tmp/(như vậy lslà chạy mà không có lý luận và liệt kê các thư mục hiện hành).

Một số watchtriển khai trong danh mục đầu tiên (như dự án từ Procps-ng trên Linux) chấp nhận một -xtùy chọn để làm cho chúng hoạt động giống như watchthể loại thứ hai. Vì vậy, với đó, bạn có thể làm:

watch -x sh -c 'ls /tmp/|wc -l'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.