Chmod y -r + r

13

He intentado llamar al comando chmod en el orden incorrecto. chmod file.txt -rEsto funcionó por alguna razón. chmod file.txt +rPor otro lado se negó a trabajar. ¿Por qué es esto? ¿Por qué razón un comando funciona y el otro no?

TestyTentacleLinux
fuente

Respuestas:

18

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 chmodrequiere 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 filees preferible y chmod -w file(sin el --) se queja si se comporta de manera diferente a lo que chmod a-w file" haría.

Brevemente, las opciones analizadas por getopttienen el prefijo a -. Como en ls -a, aes una opción. La forma larga ls --alltiene allcomo opción. rm -rf(equivalente a rm -r -f) tiene ambas ry fopciones.

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 fileo en chmod -- -w filelugar 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.txtserí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.txttodavía funciona porque -rse interpreta como una ropción corta y con mayúsculas especiales.
  • chmod -- -r file.txtes correcto y funciona porque -rse interpreta posicionalmente como el modo. Esto difiere del caso sin --porque con --el -rno se interpreta como una opción .
  • chmod file.txt -rtodavía funciona porque -rse interpreta como una ropció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 +rno funciona porque +res un operando, no una opción. El primer operando ( file.txt) se interpreta como un modo ... y no se analiza.
Beto
fuente
44
Esto puede tener consecuencias interesantes si tiene un archivo llamado, por ejemplo, a+rwxy hace algo así chmod * +r, y el a+rwxarchivo aparece primero en la expansión global.
Jörg W Mittag
1
O un archivo llamado "-rf" en el caso de "rm *".
Edheldil
@Edheldil Sí, tienes razón. Esto parece algo que debería abordarse (y un error, al igual que si la entrada no se desinfectara correctamente.)
TestyTentacleLinux
Tenga en cuenta que la sintaxis OP no es POSIX man7.org/linux/man-pages/man1/getopt.1.html#SCANNING_MODES
Steven Penny
@StevenPenny Eso es irrelevante. En primer lugar, la página de manual vinculada es la sección 1, es decir, el getopt comando , no la rutina de la biblioteca en la sección 3 . En segundo lugar, eso se refiere a optstring, es decir, la lista de opciones aceptadas (en chmodorigen optstringestá 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 argumentos argv que contiene los argumentos pasados ​​al programa.
Bob