A diferença pode ser vista 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 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
No caso de backquote, ls /tmp
é passado como um argumento único para o -c
to sh
, que é executado conforme o esperado. Sem esse backquote, o comando será dividido quando watch
executar sh
, que por sua vez executará o sh
fornecido, de modo que somente ls
seja passado como o argumento para -c
, significando que o sub-sub sh
executará apenas o comando ls
, e listará o conteúdo do diretório de trabalho atual.
Então, por que a complicação de sh -c ...
? Por que não executar simplesmente watch 'ls /tmp|wc -l'
?