I'm trying to watch number of files in my /tmp/ directory. For this I thought this command would work:watch sh -c 'ls /tmp/|wc -l'But it appears to work as if ls had no arguments. Namely, I'm in ~, and I get number of files there instead of /tmp/. I found a workaround, which seems to work:watch sh -c 'ls\ /tmp/|wc -l'But why do I need to escape the space between ls and /tmp/? How is the command transformed by watch so that ls output is feeded to wc, but /tmp/ is not passed as argument to ls?
Why does `watch` make `ls /tmp` list contents of $HOME?
shell;ls;watch
The difference may be seen via 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 shbq.29218:execve(/usr/bin/watch, [watch, sh, -c, ls\\ /tmp/|wc -l], [/* 54 vars */]) = 0bq.29219:execve(/bin/sh, [sh, -c, sh -c ls\\ /tmp/|wc -l], [/* 56 vars */]) = 0bq.29220:execve(/bin/sh, [sh, -c, ls /tmp/], [/* 56 vars */]) = 0$ grep exec nobq* | grep shnobq.29227:execve(/usr/bin/watch, [watch, sh, -c, ls /tmp/|wc -l], [/* 54 vars */]) = 0nobq.29228:execve(/bin/sh, [sh, -c, sh -c ls /tmp/|wc -l], [/* 56 vars */]) = 0nobq.29229:execve(/bin/sh, [sh, -c, ls, /tmp/], [/* 56 vars */]) = 0In the backquote case, ls /tmp is passed as a single argument to the -c to sh, which runs as expected. Without this backquote, the command is instead word split when watch runs sh which in turn runs the supplied sh, so that only ls is passed as the argument to -c, meaning that the sub-subsh will only run a bare ls command, and lists the contents of the current working directory.So, why the complication of sh -c ...? Why not simply run watch 'ls /tmp|wc -l' ?