Chmod e -r + r

13

Eu tentei chamar o comando chmod na ordem errada. chmod file.txt -r Isso funcionou por algum motivo. chmod file.txt +r Por outro lado, recusou-se a trabalhar. Por que é isso? Por que razão um comando funciona e o outro não?

    
por TestyTentacleLinux 27.09.2018 / 09:10

1 resposta

18

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 modo para vir em primeiro lugar, assim como GNU 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, and chmod -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 de r 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 curta r 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.
por 27.09.2018 / 09:27

Tags