なぜ `watch`は$ lsの内容を` ls / tmp`にリストするのですか?


13

/tmp/ディレクトリ内のファイルの数を監視しようとしています。このため、私はこのコマンドが機能すると思った:

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

しかしls、引数がないかのように動作するようです。つまり、私はにいて~、そこに多数のファイルを取得します/tmp/。私は回避策を見つけましたが、それはうまくいくようです:

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

しかし、なぜlsとの間のスペースをエスケープする必要があるの/tmp/ですか?どのようにコマンドがによって変換されるwatchように、ls出力がにfeededされwcますが、/tmp/に引数として渡されていませんかls


1
watch "sh -c 'ls /tmp | wc -l'"このコマンドを実行すると、目的の効果が得られます。これは監視のせいではありません。試してみてsh -c ls /tmp、ホームディレクトリを取得します(しかし、理由は
わかり

8
答えではありませんが、あなたはwatch間違って使用しています。あなたが渡すコマンドwatchは順番にwatchto によって供給されるsh -cので、あなたは事実上sh -c2回やっています。
-iruvar

好奇心are盛な方は、ソースもご覧ください。
-michas

1
@JacobMinshall、その理由は簡単です:はの/tmp引数でshあり、その場合、の引数ではありませんls
チャールズダフィー

回答:


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単一の引数として渡される-csh予想されるように実行され、。ときに、このバッククォートせずに、コマンドではなく、単語の分割でwatch実行されますが、sh順番に供給し実行するshだけなのでことを、ls引数として渡され-cたサブサブがあることを意味し、sh唯一の裸実行するlsコマンドを、現在の作業のリスト内容をディレクトリ。

それでは、なぜ複雑なのsh -c ...ですか?単純に実行しないのはなぜwatch 'ls /tmp|wc -l'ですか?


ああ、straceそれを試そうとは思わなかった。
ルスラン

1
実際、 `は逆引用符(または逆ティック)です。この質問はバックスラッシュである\についてです。
G-Manは「Reinstate Monica」と言います

@Ruslan:私はこのコメント投稿この回答には、それはコメントですので、この答えに。thrigは「で言うバッククォート、ケースls /tmp...さ」と「これがないとバッククォート、コマンドがある...」、および使用bqしてnobq、すべてを参照したときに、ファイル名としてバックスラッシュあなたにls\ /tmpコマンド。
G-Manは「Reinstate Monica」と言います

8

watchコマンドには主に2つのカテゴリがあります(コマンドを定期的に実行するものwatchは標準コマンドではありませんwatch。FreeBSDの別のtty行でスヌーピングのような完全に異なるシステムもあります)。

引数とスペースの連結をすでにシェルに渡している(実際にはcallを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 の実装など)は、2番目のカテゴリの-xように動作させるオプションを受け入れwatchます。そのため、次のことができます。

watch -x sh -c 'ls /tmp/|wc -l'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.