He intentado llamar al comando chmod en el orden incorrecto. chmod file.txt -r
Esto funcionó por alguna razón. chmod file.txt +r
Por otro lado se negó a trabajar. ¿Por qué es esto? ¿Por qué razón un comando funciona y el otro no?
Esta es una peculiaridad de cómo GNU chmod maneja la entrada, y no es portátil para todas las implementaciones de chmod compatibles con POSIX.
Tenga en cuenta que la sintaxis de línea y línea POSIX chmod
requiere que el modo sea lo primero, al igual que GNUchmod
(las opciones también deben ser anteriores al modo). Cualquier otra cosa es una peculiaridad de implementación no documentada.
Ahora, sobre por qué sucede en esta implementación particular:
Se insinúa en el manual :
Normalmente, sin embargo, "
chmod a-w file
es preferible ychmod -w file
(sin el--
) se queja si se comporta de manera diferente a lo quechmod a-w file
" haría.
Brevemente, las opciones analizadas por getopt
tienen el prefijo a -
. Como en ls -a
, a
es una opción. La forma larga ls --all
tiene all
como opción. rm -rf
(equivalente a rm -r -f
) tiene ambas r
y f
opciones.
Todo lo demás es un argumento sin opción, técnicamente llamado operandos . Me gusta llamar a estos argumentos posicionales , ya que su significado está determinado por su posición relativa. En chmod
, el primer argumento posicional es el modo y el segundo argumento posicional es el nombre del archivo.
Óptimamente, el modo no debe conducir con a -
. Si lo hace, debe usar --
para forzar el análisis como un operando en lugar de una opción (es decir, usar chmod a-w file
o en chmod -- -w file
lugar de chmod -w file
. Esto también lo sugiere POSIX.
Si observa el código fuente , notará que usa getopt para analizar las opciones de la línea de comandos. Aquí, hay un manejo especial para modos 'incorrectos' 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 tu ejemplo:
chmod a-r file.txt
sería la invocación más robusta .chmod +r file.txt
funciona porque el primer argumento se interpreta posicionalmente como el modo.chmod -r file.txt
todavía funciona porque -r
se interpreta como una r
opción corta y con mayúsculas especiales.chmod -- -r file.txt
es correcto y funciona porque -r
se interpreta posicionalmente como el modo. Esto difiere del caso sin --
porque con --
el -r
no se interpreta como una opción .chmod file.txt -r
todavía funciona porque -r
se interpreta como una r
opción corta y con mayúsculas especiales. Las opciones no dependen de la posición. Esto técnicamente abusa de una peculiaridad indocumentada.chmod file.txt +r
no funciona porque +r
es un operando, no una opción. El primer operando ( file.txt
) se interpreta como un modo ... y no se analiza.
a+rwx
y hace algo asíchmod * +r
, y ela+rwx
archivo aparece primero en la expansión global.getopt
comando , no la rutina de la biblioteca en la sección 3 . En segundo lugar, eso se refiere aoptstring
, es decir, la lista de opciones aceptadas (enchmod
origenoptstring
está establecida en"Rcfvr::w::x::X::s::t::u::g::o::a::,::+::=::"
). La sección vinculada "MODOS DE ESCANEO" no tiene nada que ver con la matriz de argumentosargv
que contiene los argumentos pasados al programa.