#linux #bash #shell
#linux #bash #оболочка
Вопрос:
Пытаюсь исправить доступные для записи файлы и получаю сообщение об ошибке ниже:
chmod: missing operand after a t
вот мой код
df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -0002 -a ! -perm -1000 2>/dev/null | xargs chmod a t
Есть мысли?
Комментарии:
1. Если бы вы использовали
-exec
вместоxargs
, у вас не было бы этой проблемы (или нескольких других).2. Если у вас GNU
xargs
, вы можете использовать опцию--no-run-if-empty
(aka-r
), чтобы избежать выполнения команды один раз, даже если нет аргументов (поведение, требуемое POSIX, вероятно, из уважения к историческому прецеденту, а не потому, что это казалось действительно хорошей идеей). Но вам лучше избегать использованияxargs
.3. @JonathanLeffler Все еще вызывает команду, когда нет аргументов, почему, это похоже … все еще расширяется до нерасширенного шаблона глобуса, когда он ничему не соответствует, и передает бесполезный аргумент.
4. @Kaz, … есть чертовски веская причина
nullglob
, по умолчанию отключена: широко доступные программы командной строки имеют поведение по умолчанию, которое они используют, когда не передают аргументы; передача им глобального литерала означает, что вместо возврата к этому поведению по умолчанию у них есть возможность выдать ошибку. Поведение GNU xargs по умолчанию, напротив, — это то, на что у меня нет защиты.
Ответ №1:
Здесь вообще нет необходимости xargs
— это источник ваших ошибок, и он мог бы стать источником еще большего количества ошибок, если бы у вас было содержимое, смонтированное в каталоге с пробелами или кавычками (или буквенными обратными косыми чертами) в его имени.
{
read _ # consume header
while IFS= read -r dirname; do # ...iterate over later lines...
find "$dirname" -xdev -type d
'(' -perm -0002 -a ! -perm -1000 ')'
-exec chmod a t '{}' 2>/dev/null
done
} < <(df --output=target --local) # tell df to emit only the one column you want
Чтобы пояснить, почему xargs является источником ошибок в этом коде:
- GNU xargs (но не BSD xargs) вызовет команду без каких-либо аргументов, если ее входные данные не содержат содержимого. Это ваша непосредственная проблема.
- Все реализации xargs, совместимые с POSIX, будут анализировать кавычки и обратную косую черту (используя их) и разделять ввод на пробелы, если только расширения не используются для указания ему поступать иначе (например,
-0
[тем самым требуя ввода с разделителями NUL] или, в версии GNU,-d $'n'
[для корректной работы с разделителями новой строки]). Это означает, что если бы у вас был контент, смонтированный в/media/Movie Name With Spaces
, xargs пытался бы работатьfind
с/media/Movie
,Name
,With
, иSpaces
отдельно;/media/Movie Name With Spaces "And Quotes"
сделал бы то же самое, но сAnd Quotes
(без пробелов!) в виде одного слова.
Более того, здесь нет никакой выгоды от использования xargs
, если ваш find
код использует современные (2006 года) Расширения POSIX: -exec somecommand {}
передает столько аргументов somecommand
, сколько поместится при каждом вызове, точно так же, как xargs somecommand
и делает.
Ответ №2:
Это происходит, когда вы не предоставляете аргументов для chmod
:
$ chmod a x
chmod: missing operand after ‘a x’
Try 'chmod --help' for more information.
Таким образом, предположительно, команда:
df --local -P | awk {'if (NR!=1) print $6'} |
xargs -I '{}' find '{}' -xdev -type d -perm -0002 -a ! -perm -1000 2>/dev/null
не генерирует никаких выходных данных, т.Е. У вас нет ни одного каталога с соответствующими требуемыми perm
ограничениями в заданных каталогах для поиска. Запустите только эту команду, без chmod
, чтобы убедиться в этом.