Команда 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передаются как $0и $1в bash, поэтому они фактически игнорируются. Запустите что-то вроде:

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 +++

Связанный контент