Eu tentei chamar o comando chmod na ordem errada. chmod file.txt -rIsso funcionou por algum motivo. chmod file.txt +rPor outro lado, se recusou a trabalhar. Por que é isso? Por que razão um comando funciona e o outro não?
Eu tentei chamar o comando chmod na ordem errada. chmod file.txt -rIsso funcionou por algum motivo. chmod file.txt +rPor outro lado, se recusou a trabalhar. Por que é isso? Por que razão um comando funciona e o outro não?
Respostas:
Esta é uma peculiaridade de como o GNU chmod lida com a entrada e não é portátil para todas as implementações de chmod compatíveis com POSIX.
Observe que a sintaxe da linha de co-linha e POSIX chmodexige que o modo seja o primeiro, assim como o GNUchmod (as opções também devem vir antes do modo). Qualquer outra coisa é uma peculiaridade de implementação não documentada.
Agora, sobre por que isso acontece nesta implementação específica:
É sugerido no manual :
Normalmente, porém, '
chmod a-w file' é preferível echmod -w file(sem o--) reclama se ele se comporta de maneira diferente do que 'chmod a-w file' faria.
Resumidamente, as opções analisadas por getoptsão prefixadas com a -. Como em ls -a, aé uma opção. A forma longa ls --alltem allcomo uma opção. rm -rf(equivalente a rm -r -f) possui ambos re fopções.
Tudo o resto é um argumento de não opção, tecnicamente chamado operandos . Gosto de chamar esses argumentos posicionais , pois seu significado é determinado por sua posição relativa. Em chmod, o primeiro argumento posicional é o modo e o segundo argumento posicional é o nome do arquivo.
Idealmente, o modo não deve levar a -. Se isso acontecer, você deve --forçar a análise como um operando em vez de uma opção (por exemplo, use chmod a-w fileou em chmod -- -w filevez de chmod -w file. Isso também é sugerido pelo POSIX.
Se você olhar o código fonte , notará que ele usa getopt para analisar as opções da 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 o seu exemplo:
chmod a-r file.txtseria a invocação mais robusta .chmod +r file.txt funciona porque o primeiro argumento é posicionalmente interpretado como o modo.chmod -r file.txtainda funciona porque -ré interpretado como uma ropção curta e com uma caixa especial.chmod -- -r file.txtestá correto e funciona porque o -ré posicionalmente interpretado como o modo. Isso difere do caso sem, --porque com --o -rnão é interpretado como uma opção .chmod file.txt -rainda funciona porque -ré interpretado como uma ropção curta e com uma caixa especial. As opções não dependem da posição. Isso tecnicamente abusa de uma peculiaridade não documentada.chmod file.txt +rnão funciona porque +ré um operando, não uma opção. O primeiro operando ( file.txt) é interpretado como um modo ... e falha ao analisar.getopt comando , não a rotina da biblioteca na seção 3 . Em segundo lugar, isso se refere a optstring, ou seja, a lista de opções aceitas (na chmodfonte optstringestá definida como "Rcfvr::w::x::X::s::t::u::g::o::a::,::+::=::"). A seção "SCANNING MODES" vinculada não tem nada a ver com a matriz de argumentos argv que contém os argumentos passados para o programa.
a+rwxe fizer algo assimchmod * +r, e oa+rwxarquivo ocorrer primeiro na expansão glob.