Chmod і -r + r


13

Я намагався викликати команду chmod у неправильному порядку. chmod file.txt -rЦе спрацювало чомусь. chmod file.txt +rЗ іншого боку, відмовився працювати. Чому це? З якої причини одна команда працює, а інша ні?

Відповіді:


18

Це вигадка щодо того, як GNU chmod обробляє введення, і не є переносним для всіх POSIX-сумісних реалізацій chmod.

Зауважте, що синтаксис команд-рядків POSIX chmodвимагає, щоб режим був першим, як і 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, перший позиційний аргумент - це режим, а другий позиційний аргумент - це ім'я файлу.

Оптимально режим не повинен вести з a -. Якщо це так, вам слід використовувати --для примусового розбору як операнда замість опції (тобто використання 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файл стане першим у глобальному розширенні.
Йорг W Міттаг

1
Або файл з назвою "-rf" у разі "rm *".
Edheldil

@Edheldil Так, ви праві. Це здається чимось, на що слід вирішити (і помилка, так само, якби введення не було дезінфіковано належним чином.
TestyTentacleLinux

Зауважте, що синтаксис OP не є POSIX man7.org/linux/man-pages/man1/getopt.1.html#SCANNING_MODES
Стівен Пенні,

@StevenPenny Це не має значення. По-перше, пов'язана сторінка - це розділ 1, тобто getopt команда , а не звичайна бібліотека в розділі 3 . По-друге, це посилання на optstring, тобто список прийнятих параметрів (у chmodджерелі optstringвстановлено "Rcfvr::w::x::X::s::t::u::g::o::a::,::+::=::"). Зв'язаний розділ "РЕЖИМ сканування" не має нічого спільного з масивом аргументів argv який містить аргументи, передані в програму.
Боб
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.