シェルのwatchコマンドがファイル名を認識しない

シェルのwatchコマンドがファイル名を認識しない

試してみたところwatch bash -c 'du -h /etc/passwd && df -h'、ファイルへのパスが完全に無視され、代わりにdu -h現在の作業ディレクトリが実行されたようです。 を実行したときも同じ結果が見られwatch bash -c 'stat /etc/passwd && df -h'、エラーstatが返されましたstat: missing operand。対照的に、watch -e "command /path/to/file"または を使用するとwatch "command /path/to/file"問題なく動作します。

ではなぜwatch bash -c 'du -h /etc/passwd && df -h'動作しないのでしょうか? これwatchは の問題ですか、それともbash引数分割の問題ですか?

答え1

watchは引数を に渡してコマンドを実行しますsh -c。したがって、最終的に実行されるのは次のようになります。

sh -c 'bash -c du -h /etc/passwd && df -h'

実行中のシェルは、適用した最初の引用符の層を削除します。 は-h、および/etc/passwdとして bash に渡されるため、実質的に無視されます。次のようなものを実行します。$0$1

watch 'du -h /etc/passwd && df -h'
watch "bash -c 'du -h /etc/passwd && df -h'"

確認するには、次を使用しますstrace:

strace -fe execve -o log watch bash -c 'du -h /etc/passwd && df -h'

以下がlog含まれます:

17132 execve("/usr/bin/watch", ["watch", "bash", "-c", "du -h /etc/passwd && df -h"], [/* 40 vars */]) = 0
17134 execve("/bin/sh", ["sh", "-c", "bash -c du -h /etc/passwd && df "...], [/* 42 vars */]) = 0
17135 execve("/bin/bash", ["bash", "-c", "du", "-h", "/etc/passwd"], [/* 42 vars */]) = 0
17135 execve("/usr/bin/du", ["du"], [/* 42 vars */]) = 0
17135 +++ exited with 0 +++

関連情報