Я попытался вызвать команду chmod в неправильном порядке. chmod file.txt -rЭто сработало по какой-то причине. chmod file.txt +rС другой стороны отказался работать. Почему это? По какой причине одна команда работает, а другая нет?
Я попытался вызвать команду chmod в неправильном порядке. chmod file.txt -rЭто сработало по какой-то причине. chmod file.txt +rС другой стороны отказался работать. Почему это? По какой причине одна команда работает, а другая нет?
Ответы:
Это извращение того, как GNU chmod обрабатывает ввод, и оно не переносимо для всех POSIX-совместимых реализаций chmod.
Обратите внимание, что для синтаксиса строки coomand-строки POSIXchmod сначала требуется режим, так же как и для GNUchmod (опции также должны предшествовать режиму). Все остальное - недокументированная особенность реализации.
Теперь о том, почему это происходит в этой конкретной реализации:
На это намекают в руководстве :
Обычно, однако, «
chmod a-w file» предпочтительнее, иchmod -w file(без--) жалуется, если он ведет себя не так, как «chmod a-w file».
Вкратце, анализируемые опции getoptимеют префикс a -. Как в ls -a, aэто вариант. Длинная форма ls --allимеет allв качестве опции. rm -rf(эквивалентно rm -r -f) имеет как rи fварианты.
Все остальное является необязательным аргументом, технически называемым операндами . Мне нравится называть эти позиционные аргументы, так как их значение определяется их относительным положением. В chmodпервой позиционной аргумент режим и второй позиционный аргумент является именем файла.
Оптимально, режим не должен вести с -. Если это так, вы должны использовать --принудительный синтаксический анализ как операнд вместо опции (то есть использовать chmod a-w fileили chmod -- -w fileвместо chmod -w file. Это также предлагается POSIX.
Если вы посмотрите на исходный код , вы заметите, что он использует getopt для разбора параметров командной строки. Здесь есть специальная обработка для «неправильных» режимов, таких как -w:
case 'r':
case 'w':
case 'x':
case 'X':
case 's':
case 't':
case 'u':
case 'g':
case 'o':
case 'a':
case ',':
case '+':
case '=':
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
/* Support nonportable uses like "chmod -w", but diagnose
surprises due to umask confusion. Even though "--", "--r",
etc., are valid modes, there is no "case '-'" here since
getopt_long reserves leading "--" for long options. */
Принимая ваш пример:
chmod a-r file.txtбудет самым надежным вызовом.chmod +r file.txt работает, потому что первый аргумент позиционно интерпретируется как режим.chmod -r file.txtвсе еще работает, потому что -rинтерпретируется как короткий rвариант и в специальном случае.chmod -- -r file.txtявляется правильным и работает, потому что -rпозиционно интерпретируется как режим. Это отличается от случая , не --потому , что с не интерпретируется как вариант .---rchmod file.txt -rвсе еще работает, потому что -rинтерпретируется как короткий rвариант и в специальном случае. Опции не зависят от позиции. Это технически нарушает недокументированную причуду.chmod file.txt +rне работает, потому что +rэто операнд, а не опция. Первый операнд ( file.txt) интерпретируется как режим ... и не может разобрать.getopt Команда , а не подпрограмма библиотеки в разделе 3 . Во-вторых, это относится к optstringсписку принятых опций (в chmodисточнике optstringустановлено значение "Rcfvr::w::x::X::s::t::u::g::o::a::,::+::=::"). Связанный раздел «РЕЖИМЫ СКАНИРОВАНИЯ» не имеет ничего общего с массивом аргументов, argv который содержит аргументы, переданные в программу.
a+rwxи вы делаете что-то вроде этогоchmod * +r, иa+rwxфайл оказывается первым в расширении glob.