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.
a+rwxet faites quelque chose commechmod * +r, et que lea+rwxfichier arrive en premier dans l'expansion globale.