Le module Python os.chmod (fichier, 664) ne modifie pas l'autorisation en rw-rw-r— mais -w - wx ----

111

Récemment, j'utilise le module Python os, lorsque j'ai essayé de modifier l'autorisation d'un fichier, je n'ai pas obtenu le résultat attendu. Par exemple, j'avais l'intention de changer l'autorisation en rw-rw-r--,

os.chmod("/tmp/test_file", 664)

L'autorisation de propriété est en fait -w - wx --- (230)

--w--wx--- 1 ag ag 0 Mar 25 05:45 test_file

Cependant, si je change 664 en 0664 dans le code, le résultat est exactement ce dont j'ai besoin, par exemple

os.chmod("/tmp/test_file", 0664)

Le résultat est:

-rw-rw-r-- 1 ag ag 0 Mar 25 05:55 test_file

Quelqu'un pourrait-il aider à expliquer pourquoi ce 0 en tête est si important pour obtenir le résultat correct?

AplusG
la source
33
Octal. Octal. Octal.
Cole Johnson
6
J'ai ouvert un problème pour la documentation python sur bugs.python.org/issue25377 car cela devrait être clair dans la documentation.
Karl Richter

Réponses:

130

J'ai trouvé ça sur un autre forum

Si vous vous demandez pourquoi ce zéro non significatif est important, c'est parce que les autorisations sont définies comme un entier octal et que Python traite automatiquement tout entier avec un zéro non significatif comme octal. Donc os.chmod ("fichier", 484) (en décimal) donnerait le même résultat.

Ce que vous faites est de passer 664ce qui en octal est1230

Dans votre cas, vous auriez besoin

os.chmod("/tmp/test_file", 436)

[Mise à jour] Remarque, pour Python 3, vous avez le préfixe avec 0o (zéro oh). PAR EXEMPLE,0o666

RedBaron
la source
1
Merci, mais je suis toujours confus que, 484 en décimal signifie 744 en octal, ce qui a du sens dans le fil que vous avez mentionné dans le forum. Cependant, si je donne 644 en décimal, cela passe à 1204 en octal. Quel est le rapport entre 1204 et 230 en octal?
AplusG
2
@AplusG: le 1n'est pas écarté! C'est le bit sticky / setuid / setgid, et 1 signifie sticky. En utilisant, ls -lvous remarquerez peut-être que les autorisations incluent désormais un Tà la fin ...
MestreLion
2
plus facile d'ajouter le 0 et de le rendre octal :)
radtek
10
Remarque, pour Python 3, vous avez le préfixe avec 0o (zéro oh).
Mawg dit de réintégrer Monica le
1
J'utilise 0o en python 2.7.10
Wyrmwood
125

Donc, pour les personnes qui veulent une sémantique similaire à:

$ chmod 755 somefile

Utilisation:

$ python -c "import os; os.chmod('somefile', 0o755)"

Si votre Python est plus ancien que 2.6:

$ python -c "import os; os.chmod('somefile', 0755)"
Dima
la source
12
Le format python3 fonctionne également en python 2.7.9. Je n'ai pas vérifié les versions antérieures.
Fred Mitchell
3
La syntaxe Python 3 fonctionne de nouveau vers Python 2.6 docs.python.org/3/whatsnew
Pete
Travaillez pour moi tks!
LandiLeite
00755Cela devrait probablement être le cas , juste pour préciser où vont les bits suid / sgid / sticky, au cas où un développeur plus tardif viendrait et voudrait utiliser cet ancien script, par exemple, sgid avec 2755mais ne peut pas comprendre pourquoi les permanentes sont complètement foutues. ;)
dannysauer le
10

en tête 0signifie qu'il s'agit d'une constante octale , pas d'une décimale. et vous avez besoin d'un octal pour changer de mode de fichier.

les autorisations sont un masque de bits, par exemple, rwxrwx---sont 111111000en binaire, et il est très facile de grouper les bits par 3 pour les convertir en octal, que de calculer la représentation décimale.

0644(octal) est 0.110.100.100en binaire (j'ai ajouté des points pour la lisibilité), ou, comme vous pouvez le calculer, 420en décimal.

Lenik
la source
5

Utilisez des symboles d'autorisation au lieu de chiffres

Votre problème aurait été évité si vous aviez utilisé les symboles d'autorisation plus sémantiquement nommés plutôt que les nombres magiques bruts, par exemple pour 664:

#!/usr/bin/env python3

import os
import stat

os.chmod(
    'myfile',
    stat.S_IRUSR |
    stat.S_IWUSR |
    stat.S_IRGRP |
    stat.S_IWGRP |
    stat.S_IROTH
)

Ceci est documenté sur https://docs.python.org/3/library/os.html#os.chmod et les noms sont les mêmes que les valeurs de l' API C POSIX documentées sur man 2 stat.

Un autre avantage est la plus grande portabilité comme mentionné dans la documentation:

Remarque: Bien que Windows prenne en charge chmod(), vous ne pouvez définir l'indicateur de lecture seule du fichier qu'avec lui (via les constantes stat.S_IWRITEet stat.S_IREADou une valeur entière correspondante). Tous les autres bits sont ignorés.

chmod +xest démontré à: Comment faire un simple "chmod + x" depuis Python?

Testé dans Ubuntu 16.04, Python 3.5.2.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
1
C'est la bonne façon de traiter le problème.
carthurs
Je sais cela à la manière de python mais ça ne pourrait guère être plus laid :)
Tomasz Swider
2

Si vous avez les autorisations souhaitées enregistrées dans la chaîne, faites

s = '660'
os.chmod(file_path, int(s, base=8))
mc.dev
la source
0

Utiliser les masques stat. * Bit me semble la manière la plus portable et la plus explicite de le faire. Mais d'un autre côté, j'oublie souvent la meilleure façon de gérer cela. Donc, voici un exemple de masquage des autorisations «groupe» et «autres» et de laisser les autorisations «propriétaire» intactes. L'utilisation de masques et de soustractions est un modèle utile.

import os
import stat
def chmodme(pn):
    """Removes 'group' and 'other' perms. Doesn't touch 'owner' perms."""
    mode = os.stat(pn).st_mode
    mode -= (mode & (stat.S_IRWXG | stat.S_IRWXO))
    os.chmod(pn, mode)
Jason Drew
la source