为什么`watch`使`ls / tmp`列出$ HOME的内容?


13

我正在尝试查看/tmp/目录中的文件数。为此,我认为此命令将起作用:

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

但这似乎ls没有任何论据就可以工作。即,我在中~,在那里我得到的文件数代替/tmp/。我找到了一种解决方法,该方法似乎可行:

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

但是,为什么我要逃避之间的空间ls/tmp/?命令如何转换,watch以便将ls输出馈送到wc,但/tmp/不作为参数传递给ls


1
watch "sh -c 'ls /tmp | wc -l'"执行此命令应获得预期的效果。这不是sh -c ls /tmp
看错

8
不是答案,而是您使用watch不正确。传递给的命令watch反过来又传递给watchsh -c,因此实际上执行了sh -c两次。
iruvar

如果您好奇,也可以看看源代码
michas

1
@JacobMinshall,其原因很简单:在这种情况下,它/tmp是的参数sh,而不是的参数ls
查尔斯·达菲,2016年

Answers:


17

可以通过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

在反引号的情况下,ls /tmp作为单个参数传递给-cto sh,后者按预期运行。如果没有该反引号,则该命令将在watch运行时进行单词拆分sh,然后运行提供的sh,以便仅ls将其作为参数传递给-c,这意味着子-sub sh将仅运行裸ls命令,并列出当前工作的内容目录。

那么,为什么会并发症sh -c ...呢?为什么不简单地运行watch 'ls /tmp|wc -l'呢?


哦,确实,没想到要尝试strace
Ruslan

1
实际上,`是反引号(或反勾号)。这个问题是关于\,即反斜杠。
G-Man说'恢复莫妮卡'

@Ruslan:我在此答案上发布了此评论因为它是对该答案的评论。thrig说:“在反引号的情况下,ls /tmp是...”和“如果没有这个反引号,命令是......”,并且使用bqnobq文件名,而在所有的,而指的是反斜杠在你的ls\ /tmp命令。
G-Man说'恢复莫妮卡'

8

有两种主要的watch命令类别(其中一些命令是定期运行的,watch不是标准命令,甚至watch有些系统在做一些完全不同的事情,例如在FreeBSD上的另一tty行上监听)。

一种已经将其带有空格的参数的连接传递给了一个外壳程序(它实际上是在调用sh -c <concatenation-of-arguments>),而另一种只是运行了使用指定的参数指定的命令而不调用外壳程序。

您处于第一种情况,因此您只需要:

watch 'ls /tmp/|wc -l'

当您这样做时:

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

watch实际运行:

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

sh -c ls /tmp/运行ls,其中内嵌脚本$0/tmp/(所以ls不加参数,并列出当前目录下运行)。

watch第一类中的某些实现(例如Linux上procps-ng的实现)接受一个-x选项,使它们的行为类似于watch第二类。因此,在那里,您可以执行以下操作:

watch -x sh -c 'ls /tmp/|wc -l'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.