Dlaczego `watch` tworzy zawartość listy` ls / tmp` w $ HOME?


13

Próbuję oglądać liczbę plików w moim /tmp/katalogu. W tym celu myślałem, że to polecenie zadziała:

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

Ale wydaje się, że działa tak, jakby lsnie miał żadnych argumentów. Mianowicie, jestem w ~środku i zamiast tego otrzymuję tam liczbę plików /tmp/. Znalazłem obejście, które wydaje się działać:

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

Ale dlaczego muszę uciec z przestrzeni między lsi /tmp/? W jaki sposób polecenie jest przekształcane, watchaby lsdane wyjściowe były podawane do wc, ale /tmp/nie były przekazywane jako argument do ls?


1
watch "sh -c 'ls /tmp | wc -l'"Wykonanie tego polecenia powinno uzyskać pożądany efekt. To nie jest wina, spróbuj, sh -c ls /tmpa dostaniesz swój katalog domowy (ale nie mam pojęcia, dlaczego ...)
Jacob Minshall,

8
Nie odpowiedź, ale używasz watchniewłaściwie .Powierzchnia polecenie, które przechodzą do watchz kolei jest zasilany przez watchdo sh -c, więc jesteś w efekcie robi sh -cdwa razy.
iruvar

Jeśli jesteś ciekawy, możesz także zajrzeć do źródła .
michas

1
@JacobMinshall, dlaczego jest prosty: /tmpJest to argument, aby shw tym przypadku nie argumentować ls.
Charles Duffy

Odpowiedzi:


17

Różnicę można zobaczyć poprzez 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

W przypadku cudzysłowu ls /tmpjest przekazywany jako pojedynczy argument -cdo sh, który działa zgodnie z oczekiwaniami. Bez tego cudzysłowu polecenie jest zamiast tego dzielone na słowa podczas watchuruchamiania, shktóre z kolei uruchamia dostarczoną sh, tak że lsjest przekazywany tylko jako argument do -c, co oznacza, że ​​podrzędny podrzędny shuruchomi tylko nagie lspolecenie i wyświetla zawartość bieżącego działania informator.

Dlaczego więc komplikacja sh -c ...? Dlaczego po prostu nie uruchomić watch 'ls /tmp|wc -l'?


Och, rzeczywiście, nie myślałem o stracetym.
Ruslan

1
W rzeczywistości `jest odwrotnym cytatem (lub tyknięciem wstecz). To pytanie dotyczy \, który jest odwrotnym ukośnikiem.
G-Man mówi „Reinstate Monica”

@ Ruslan: opublikowałem ten komentarz do tej odpowiedzi, ponieważ jest to komentarz do tej odpowiedzi . thrig mówi „W backquote przypadku, ls /tmpto ...” i „Bez tej backquote , polecenie to ...” i używa bqi nobqjak nazwy plików, kiedy cały czas odnosząc się do backslashem w swojej ls\ /tmpkomendzie.
G-Man mówi „Reinstate Monica”

8

Istnieją dwie główne kategorie watchpoleceń (z tych, które mają być uruchamiane okresowo, watchnie jest to standardowe polecenie, są nawet systemy, w których watchdziała coś zupełnie innego, jak szpiegowanie w innej linii tty we FreeBSD).

Jeden, który już przekazuje konkatenację swoich argumentów ze spacjami do powłoki (faktycznie wywołuje sh -c <concatenation-of-arguments>) i taki, który po prostu uruchamia polecenie określone z podanymi argumentami bez wywoływania powłoki.

Jesteś w pierwszej sytuacji, więc potrzebujesz tylko:

watch 'ls /tmp/|wc -l'

Kiedy to zrobisz:

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

Twój watchfaktycznie działa:

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

I sh -c ls /tmp/uruchamia lsskrypt wbudowany gdzie $0jest /tmp/(tak lsjest uruchamiany bez argumentów i wyświetla bieżący katalog).

Niektóre watchimplementacje z pierwszej kategorii (jak ta z procps-ng w Linuksie) akceptują -xopcję, aby zachowywały się jak watchz drugiej kategorii. Dzięki temu możesz:

watch -x sh -c 'ls /tmp/|wc -l'
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.