`Watch` neden` ​​ls / tmp` $ HOME içeriğini listeliyor?


13

/tmp/Dizindeki dosya sayısını izlemeye çalışıyorum . Bunun için bu komutun işe yarayacağını düşündüm:

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

Ama sanki lshiç argümanı yokmuş gibi çalışıyor . Yani, içerideyim ~ve bunun yerine dosya sayısını alıyorum /tmp/. İşe yarayan bir çözüm buldum:

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

Ama neden arasındaki boşluğu kaçmak gerekiyor lsve /tmp/? Komut watch, lsçıktıyı beslenecek wc, ancak /tmp/argüman olarak iletilmeyecek şekilde nasıl dönüştürülür ls?


1
watch "sh -c 'ls /tmp | wc -l'"bu komutu yapmak istediğiniz etkiyi almalıdır. Bu saat hatası değil, deneyin sh -c ls /tmpve ana dizininizi alacaksınız (ama nedenini bilmiyorum ...)
Jacob Minshall

8
Sorumun cevabı değil ancak kullandığınız watchsize aktarmak olduğunu yanlış hayranlarıyla komutu watchsırayla beslenen watchiçin sh -cyaptığını yürürlükte olacak şekilde durun, sh -ciki kez.
iruvar

Merak ediyorsanız, kaynağa da bakabilirsiniz .
michas

1
@JacobMinshall, neden basittir: /tmpbir argümandır shiçin, bu durumda, değil bir argüman ls.
Charles Duffy

Yanıtlar:


17

Fark şu şekillerde görülebilir 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

Backquote durumunda, beklendiği gibi çalışan to 'ya ls /tmptek bir argüman olarak iletilir . Bu Backquote olmadan, komut kelimesi bölünmüş yerine olduğunda çalışır sırayla tedarik çalışır bu sadece bugüne, argüman olarak geçirilen alt-alt, yani sadece çıplak çalışacak şimdiki çalışma komutu ve listeler içerikleri dizin.-cshwatchshshls-cshls

Peki, neden komplikasyon sh -c ...? Neden sadece koşmuyorsun watch 'ls /tmp|wc -l'?


Gerçekten de denemeyi düşünmemiştim strace.
Ruslan

1
Aslında, `backquote (veya back-tick). Bu soru \, ters eğik çizgi ile ilgilidir.
G-Man

@Ruslan: Bu görüş gönderdi bu cevap üzerine bir yorumdur, çünkü bu cevap üzerine . thrig "In der backquote durumda, ls /tmpis ..." ve "Bu olmadan backquote , komut ..." ve kullanımları bqve nobqdosya adları gibi zaman tüm bahsederken ters eğik çizgi sizin de ls\ /tmpkomuta.
G-Man, 'Monica'yı Yeniden Başlat' diyor

8

İki ana watchkomut kategorisi vardır (komutları periyodik olarak çalıştıracak olanlardan watchstandart bir komut değildir watch, FreeBSD'deki başka bir tty satırında gözetleme gibi tamamen farklı bir şey yapan sistemler bile vardır ).

Bir argümanın boşluklarla birleştirilmesini bir kabuğa geçiren (aslında çağrıyı yapar sh -c <concatenation-of-arguments>) ve yalnızca bir kabuk çağırmadan belirtilen argümanlarla belirtilen komutu çalıştıran.

İlk durumdasınız, bu yüzden ihtiyacınız var:

watch 'ls /tmp/|wc -l'

Yaptığınızda:

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

senin watchaslında çalıştırır:

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

Ve sh -c ls /tmp/çalıştıran lssatır içi komutu $0edilir /tmp/(böylece lsargümanlar ve listeler geçerli dizin olmadan çalıştırılır).

watchİlk kategorideki bazı uygulamalar (Linux'ta procps-ng'den gelen gibi) , ikinci kategorideki -xgibi davranmalarını kabul etme seçeneğini kabul eder watch. Böylece orada şunları yapabilirsiniz:

watch -x sh -c 'ls /tmp/|wc -l'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.