Chmod и -r + r

13

Я попытался вызвать команду chmod в неправильном порядке. chmod file.txt -rЭто сработало по какой-то причине. chmod file.txt +rС другой стороны отказался работать. Почему это? По какой причине одна команда работает, а другая нет?

TestyTentacleLinux
источник

Ответы:

18

Это извращение того, как 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позиционно интерпретируется как режим. Это отличается от случая , не --потому , что с не интерпретируется как вариант .---r
  • chmod file.txt -rвсе еще работает, потому что -rинтерпретируется как короткий rвариант и в специальном случае. Опции не зависят от позиции. Это технически нарушает недокументированную причуду.
  • chmod file.txt +rне работает, потому что +rэто операнд, а не опция. Первый операнд ( file.txt) интерпретируется как режим ... и не может разобрать.
боб
источник
4
Это может иметь интересные последствия, если у вас есть файл с именем, например, a+rwxи вы делаете что-то вроде этого chmod * +r, и a+rwxфайл оказывается первым в расширении glob.
Йорг Миттаг
1
Или файл с именем "-rf" в случае "rm *".
Эдхелдил
@Edheldil Да, ты прав. Это похоже на что-то, что должно быть исправлено (и ошибка, как если бы ввод не был должным образом
очищен
Обратите внимание, что синтаксис OP не является POSIX man7.org/linux/man-pages/man1/getopt.1.html#SCANNING_MODES
Стивен Пенни,
@ StevenPenny Это не имеет значения. Во-первых, связанной man-страницей является раздел 1, т. Е. getopt Команда , а не подпрограмма библиотеки в разделе 3 . Во-вторых, это относится к optstringсписку принятых опций (в chmodисточнике optstringустановлено значение "Rcfvr::w::x::X::s::t::u::g::o::a::,::+::=::"). Связанный раздел «РЕЖИМЫ СКАНИРОВАНИЯ» не имеет ничего общего с массивом аргументов, argv который содержит аргументы, переданные в программу.
Боб