Chmod et -r + r

13

J'ai essayé d'appeler la commande chmod dans le mauvais ordre. chmod file.txt -rCela a fonctionné pour une raison quelconque. chmod file.txt +rEn revanche, a refusé de travailler. Pourquoi est-ce? Pour quelle raison une commande fonctionne-t-elle et l'autre non?

TestyTentacleLinux
la source

Réponses:

18

C'est une bizarrerie de la façon dont GNU chmod gère les entrées, et n'est pas portable pour toutes les implémentations chmod compatibles POSIX.

Notez que la syntaxe POSIXchmod coomand-line nécessite que le mode vienne en premier, tout comme GNUchmod (les options doivent également précéder le mode). Tout le reste est une bizarrerie d'implémentation non documentée.


Maintenant, expliquez pourquoi cela se produit dans cette implémentation particulière:

C'est indiqué dans le manuel :

Typiquement, cependant, " chmod a-w file" est préférable, et chmod -w file(sans le --) se plaint s'il se comporte différemment de ce que " chmod a-w file" ferait.

En bref, les options analysées par getoptsont précédées d'un -. Comme dans ls -a, aest une option. Le formulaire long ls --alla allen option. rm -rf(équivalent à rm -r -f) a les deux options ret f.

Tout le reste est un argument sans option, appelé techniquement des opérandes . J'aime appeler ces arguments positionnels , car leur signification est déterminée par leur position relative. Dans chmod, le premier argument positionnel est le mode et le deuxième argument positionnel est le nom du fichier.

De manière optimale, le mode ne doit pas conduire avec a -. Si c'est le cas, vous devez utiliser --pour forcer l'analyse en tant qu'opérande au lieu d'une option (c'est-à-dire utiliser chmod a-w fileou à la chmod -- -w fileplace de chmod -w file. Ceci est également suggéré par POSIX.


Si vous regardez le code source , vous remarquerez qu'il utilise getopt pour analyser les options de ligne de commande. Ici, il existe une gestion spéciale pour les modes «incorrects» comme -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.  */

Prenons votre exemple:

  • chmod a-r file.txtserait l' invocation la plus robuste .
  • chmod +r file.txt fonctionne parce que le premier argument est interprété comme le mode.
  • chmod -r file.txtfonctionne toujours parce que le -rest interprété comme une roption courte et un boîtier spécial.
  • chmod -- -r file.txtest correct et fonctionne car le -rest positionné comme le mode. Cela diffère du cas sans --car avec --le -rn'est pas interprété comme une option .
  • chmod file.txt -rfonctionne toujours parce que le -rest interprété comme une roption courte et un boîtier spécial. Les options ne dépendent pas de la position. Cela abuse techniquement d'une bizarrerie non documentée.
  • chmod file.txt +rne fonctionne pas car +rc'est un opérande, pas une option. Le premier opérande ( file.txt) est interprété comme un mode ... et ne parvient pas à analyser.
Bob
la source
4
Cela peut avoir des conséquences intéressantes si vous avez un fichier nommé, par exemple, a+rwxet faites quelque chose comme chmod * +r, et que le a+rwxfichier arrive en premier dans l'expansion globale.
Jörg W Mittag
1
Ou un fichier nommé "-rf" en cas de "rm *".
Edheldil
@Edheldil Yep vous avez raison. Cela semble être quelque chose qui devrait être résolu (et un bogue, tout comme si l'entrée n'a pas été correctement filtrée.
TestyTentacleLinux
Notez que la syntaxe OP n'est pas POSIX man7.org/linux/man-pages/man1/getopt.1.html#SCANNING_MODES
Steven Penny
@StevenPenny Ce n'est pas pertinent. Premièrement, la page de manuel liée est la section 1, c'est-à-dire la getopt commande , pas la routine de bibliothèque dans la section 3 . Deuxièmement, cela fait référence à optstring, c'est-à-dire la liste des options acceptées (dans la chmodsource optstringest définie sur "Rcfvr::w::x::X::s::t::u::g::o::a::,::+::=::"). La section "MODES DE NUMÉRISATION" liée n'a rien à voir avec le tableau d'arguments argv qui contient les arguments passés dans le programme.
Bob