Comment faire un simple «chmod + x» depuis Python?

119

Je souhaite créer un fichier à partir d'un script python exécutable.

import os
import stat
os.chmod('somefile', stat.S_IEXEC)

il semble os.chmodne pas «ajouter» de permissions comme le fait unix chmod. Avec la dernière ligne commentée, le fichier a le mode fichier -rw-r--r--, sans commenter, le mode fichier est ---x------. Comment puis-je simplement ajouter le u+xdrapeau tout en conservant le reste des modes intacts?

prêtre
la source

Réponses:

197

Utilisez os.stat()pour obtenir les autorisations actuelles, utilisez |to ou les bits ensemble et utilisez os.chmod()pour définir les autorisations mises à jour.

Exemple:

import os
import stat

st = os.stat('somefile')
os.chmod('somefile', st.st_mode | stat.S_IEXEC)
Ignacio Vazquez-Abrams
la source
2
Cela le rend uniquement exécutable par l'utilisateur. L'affiche posait des questions sur "chmod + x", ce qui le rend exécutable à tous les
niveaux
35
Utilisez ce qui suit pour le rendre exécutable par tout le monde ... stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH. Remarque: cette valeur est la même que l'octal 0111, vous pouvez donc simplement faire st.st_mode | 0111
eric.frederich
1
Ma réponse ci-dessous copie les bits R sur X, comme on peut s'y attendre, par exemple, d'un compilateur.
Jonathon Reinhart
Je le ferais STAT_OWNER_EXECUTABLE = stat.S_IEXEC, et j'utiliserais la constante locale lisible par l'homme au lieu du charabia.
ThorSummoner
voici une réponse non pythonique qui peut être un peu plus lisible: subprocess.check_call(['chmod', '+x', 'somefile'])et vous permet de faire plus facilement des opérations comme a+rx.
Trevor Boyd Smith
20

Pour les outils qui génèrent des fichiers exécutables (par exemple des scripts), le code suivant peut être utile:

def make_executable(path):
    mode = os.stat(path).st_mode
    mode |= (mode & 0o444) >> 2    # copy R bits to X
    os.chmod(path, mode)

Cela le rend (plus ou moins) respectueux de celui umaskqui était en vigueur lorsque le fichier a été créé: l'exécutable n'est défini que pour ceux qui savent lire.

Usage:

path = 'foo.sh'
with open(path, 'w') as f:           # umask in effect when file is created
    f.write('#!/bin/sh\n')
    f.write('echo "hello world"\n')

make_executable(path)
Jonathon Reinhart
la source
2
Les littéraux octaux ont changé dans Python 3. Au lieu de 0444, vous utiliseriez 0o444. Ou, si vous souhaitez prendre en charge les deux, écrivez simplement 292.
Kevin
1
@Kevin Il semble que la nouvelle syntaxe ait été prise en charge par Python 2.6, il semble donc raisonnable de l'utiliser. (Pour un point de référence de compatibilité, CentOS 6 est livré avec Python 2.6).
Jonathon Reinhart
2
J'ignorais que Python 3 avait supprimé les littéraux octaux traditionnels. Alors merci pour ça.
Jonathon Reinhart
13

Si vous connaissez les autorisations souhaitées, l'exemple suivant peut être le moyen de rester simple.

Python 2:

os.chmod("/somedir/somefile", 0775)

Python 3:

os.chmod("/somedir/somefile", 0o775)

Compatible avec l'un ou l'autre (conversion octale):

os.chmod("/somedir/somefile", 509)

exemples d'autorisations de référence

zerocog
la source
4
Cela devrait être os.chmod ( "/ somedir / somefile", 0o775)
ang mo
4

Vous pouvez également le faire

>>> import os
>>> st = os.stat("hello.txt")

Liste actuelle du fichier

$ ls -l hello.txt
-rw-r--r--  1 morrison  staff  17 Jan 13  2014 hello.txt

Maintenant fais ça.

>>> os.chmod("hello.txt", st.st_mode | 0o111)

et vous verrez cela dans le terminal.

ls -l hello.txt    
-rwxr-xr-x  1 morrison  staff  17 Jan 13  2014 hello.txt

Vous pouvez bit à bit ou avec 0o111 pour rendre tout exécutable, 0o222 pour rendre tout accessible en écriture et 0o444 pour rendre tout lisible.

ncmathsadist
la source
2

Respect umaskcommechmod +x

man chmoddit que si augon'est pas donné comme dans:

chmod +x mypath

puis aest utilisé mais avec umask:

Une combinaison des lettres ugoa contrôle l'accès des utilisateurs au fichier qui sera modifié: l'utilisateur qui le possède (u), les autres utilisateurs du groupe du fichier (g), les autres utilisateurs n'appartenant pas au groupe du fichier (o), ou tous utilisateurs (a). Si aucun de ceux-ci n'est donné, l'effet est comme si (a) était donné, mais les bits qui sont définis dans l'umask ne sont pas affectés.

Voici une version qui simule exactement ce comportement:

#!/usr/bin/env python3

import os
import stat

def get_umask():
    umask = os.umask(0)
    os.umask(umask)
    return umask

def chmod_plus_x(path):
    os.chmod(
        path,
        os.stat(path).st_mode |
        (
            (
                stat.S_IXUSR |
                stat.S_IXGRP |
                stat.S_IXOTH
            )
            & ~get_umask()
        )
    )

chmod_plus_x('.gitignore')

Voir aussi: Comment puis-je obtenir les autorisations de fichier par défaut en Python?

Testé dans Ubuntu 16.04, Python 3.5.2.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
1

En python3:

import os
os.chmod("somefile", 0o664)

N'oubliez pas d'ajouter le 0opréfixe car les autorisations sont définies comme un entier octal et Python traite automatiquement tout entier avec un zéro non significatif comme octal. Sinon, vous passez en os.chmod("somefile", 1230)effet, ce qui est octal de 664.

funkid
la source
1
Cela définit les autorisations sur une valeur absolue, cela ne fait pas chmod +comme demandé par OP, ce qui devrait ajouter de nouvelles autorisations aux autorisations existantes.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
0

Si vous utilisez Python 3.4+, vous pouvez utiliser le pathlib pratique de la bibliothèque standard .

Sa classe Path a des méthodes chmod et stat intégrées .

from pathlib import Path


f = Path("/path/to/file.txt")
f.chmod(f.stat().st_mode | stat.S_IEXEC)
cs01
la source