Esta é uma peculiaridade de como o GNU chmod manipula a entrada e não é portável para todas as implementações chmod compatíveis com POSIX.
Observe que a sintaxe POSIX chmod
entre linhas chmod
(as opções devem vir antes do modo também). Qualquer outra coisa é uma peculiaridade de implementação não documentada.
Agora, sobre por que isso acontece nesta implementação específica:
É sugerido em o manual :
Typically, though, ‘
chmod a-w file
’ is preferable, andchmod -w file
(without the--
) complains if it behaves differently from what ‘chmod a-w file
’ would do.
Resumidamente, as opções analisadas por getopt
são prefixadas com um -
. Como em ls -a
, a
é uma opção. A forma longa ls --all
tem all
como uma opção. rm -rf
(equivalente a rm -r -f
) tem as opções r
e f
.
Todo o resto é um argumento não opcional, tecnicamente chamado operandos . Eu gosto de chamar esses argumentos posicionais , pois o significado deles é determinado pela posição relativa deles. Em chmod
, o primeiro argumento posicional é o modo e o segundo argumento posicional é o nome do arquivo.
Na melhor das hipóteses, o modo não deve liderar com -
. Em caso afirmativo, você deve usar --
para forçar a análise como um operando em vez de uma opção (ou seja, usar chmod a-w file
ou chmod -- -w file
em vez de chmod -w file
. Isso também é sugerido por POSIX.
Se você olhar para o código-fonte , você perceberá que ele usa getopt para analisar as opções de linha de comando . Aqui, há tratamento especial para modos "incorretos", como -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. */
Tomando seu exemplo:
-
chmod a-r file.txt
seria a invocação mais robusta . -
chmod +r file.txt
funciona porque o primeiro argumento é interpretado posicionalmente como o modo. -
O
chmod -r file.txt
ainda funciona porque a-r
é interpretada como uma opção curta der
e com invólucro especial. -
chmod -- -r file.txt
está correto e funciona porque o-r
é posicionalmente interpretado como o modo. Isso difere do caso sem--
porque com--
o-r
não é interpretado como uma opção . -
O
chmod file.txt -r
ainda funciona porque a-r
é interpretada como uma opção curtar
e especial-cased. As opções não são dependentes da posição. Isso tecnicamente abusa uma peculiaridade não documentada. -
chmod file.txt +r
não funciona porque o+r
é um operando, não uma opção. O primeiro operando (file.txt
) é interpretado como um modo ... e falha ao analisar.