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 getopt
sont précédées d'un -
. Comme dans ls -a
, a
est une option. Le formulaire long ls --all
a all
en option. rm -rf
(équivalent à rm -r -f
) a les deux options r
et 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 file
ou à la chmod -- -w file
place 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.txt
serait l' invocation la plus robuste .
chmod +r file.txt
fonctionne parce que le premier argument est interprété comme le mode.
chmod -r file.txt
fonctionne toujours parce que le -r
est interprété comme une r
option courte et un boîtier spécial.
chmod -- -r file.txt
est correct et fonctionne car le -r
est positionné comme le mode. Cela diffère du cas sans --
car avec --
le -r
n'est pas interprété comme une option .
chmod file.txt -r
fonctionne toujours parce que le -r
est interprété comme une r
option 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 +r
ne fonctionne pas car +r
c'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+rwx
et faites quelque chose commechmod * +r
, et que lea+rwx
fichier arrive en premier dans l'expansion globale.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 lachmod
sourceoptstring
est 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'argumentsargv
qui contient les arguments passés dans le programme.