Wie macht man ein einfaches "chmod + x" aus Python heraus?

118

Ich möchte eine Datei aus einem Python-Skript erstellen, das ausführbar ist.

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

Es scheint os.chmod, dass Berechtigungen nicht wie bei Unix hinzugefügt werden chmod. Wenn die letzte Zeile auskommentiert ist, hat die Datei den Dateimodus -rw-r--r--, wenn sie nicht auskommentiert ist , ist der Dateimodus ---x------. Wie kann ich nur die hinzufügenu+x Flag während der Rest der Modi intakt bleibt?

Priester
quelle

Antworten:

195

Verwenden Sie os.stat()diese Option , um die aktuellen Berechtigungen abzurufen, |zu oder die Bits zusammen zu verwenden und os.chmod()die aktualisierten Berechtigungen festzulegen.

Beispiel:

import os
import stat

st = os.stat('somefile')
os.chmod('somefile', st.st_mode | stat.S_IEXEC)
Ignacio Vazquez-Abrams
quelle
2
Dies macht es nur für den Benutzer ausführbar. Das Poster fragte nach "chmod + x", wodurch es auf
allen Ebenen
35
Verwenden Sie Folgendes, um es für alle ausführbar zu machen ... stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH. Hinweis: Dieser Wert entspricht dem Oktalwert 0111, Sie können also einfach st.st_mode | ausführen 0111
eric.frederich
1
Meine Antwort unten kopiert die R-Bits nach X, wie man es von einem Compiler erwarten würde.
Jonathon Reinhart
Ich würde es tun STAT_OWNER_EXECUTABLE = stat.S_IEXECund die vom Menschen lesbare lokale Konstante anstelle der Kauderwelschkonstante verwenden.
ThorSummoner
20

Für Tools, die ausführbare Dateien generieren (z. B. Skripte), kann der folgende Code hilfreich sein:

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

Dies macht es (mehr oder weniger) respektieren die umask , was beim Erstellen der Datei gültig war: Die ausführbare Datei ist nur für diejenigen festgelegt, die lesen können.

Verwendung:

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
quelle
2
In Python 3 wurden Oktal-Literale geändert. Stattdessen 0444würden Sie verwenden 0o444. Oder wenn Sie beide unterstützen möchten, schreiben Sie einfach 292.
Kevin
1
@ Kevin Es sieht so aus, als ob die neue Syntax von Python 2.6 unterstützt wurde, daher erscheint es sinnvoll, diese zu verwenden. (Als Kompatibilitätsreferenzpunkt wird CentOS 6 mit Python 2.6 ausgeliefert.)
Jonathon Reinhart
2
Mir war nicht bewusst, dass Python 3 die traditionellen Oktalliterale entfernt hatte. Also danke dafür.
Jonathon Reinhart
11

Wenn Sie die gewünschten Berechtigungen kennen, können Sie dies anhand des folgenden Beispiels einfach halten.

Python 2:

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

Python 3:

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

Kompatibel mit beiden (Oktalumwandlung):

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

Beispiele für Referenzberechtigungen

Nullocog
quelle
4
Dies sollte os.chmod ("/ somedir / somefile", 0o775) sein
ang mo
4

Sie können dies auch tun

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

Aktuelle Auflistung der Datei

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

Mach das jetzt.

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

und Sie werden dies im Terminal sehen.

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

Sie können bitweise oder mit 0o111 alles ausführbar machen, 0o222 alles beschreibbar machen und 0o444 alles lesbar machen.

ncmathsadist
quelle
2

Respekt umaskwiechmod +x

man chmodsagt, wenn augonicht wie in gegeben ist:

chmod +x mypath

dann awird aber mit verwendet umask:

Eine Kombination der Buchstaben ugoa steuert, welcher Benutzerzugriff auf die Datei geändert wird: der Benutzer, dem sie gehört (u), andere Benutzer in der Dateigruppe (g), andere Benutzer, die nicht zur Dateigruppe gehören (o) oder alle Benutzer (a). Wenn keines davon angegeben ist, ist der Effekt so, als ob (a) angegeben worden wäre, aber Bits, die in der Umask gesetzt sind, sind nicht betroffen.

Hier ist eine Version, die dieses Verhalten genau simuliert:

#!/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')

Siehe auch: Wie kann ich die Standarddateiberechtigungen in Python erhalten?

Getestet in Ubuntu 16.04, Python 3.5.2.

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

In Python3:

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

Denken Sie daran, das 0oPräfix hinzuzufügen, da Berechtigungen als oktale Ganzzahl festgelegt sind und Python jede Ganzzahl mit einer führenden Null automatisch als oktal behandelt. Ansonsten gehen Sie os.chmod("somefile", 1230)tatsächlich vorbei , was oktal von ist 664.

funkid
quelle
1
Dadurch werden Berechtigungen auf einen absoluten Wert gesetzt, nicht chmod +wie von OP gefordert, wodurch vorhandene Berechtigungen um neue erweitert werden sollten.
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功
0

Wenn Sie Python 3.4+ verwenden, können Sie die praktische Pfadlib der Standardbibliothek verwenden .

Die Path- Klasse verfügt über integrierte chmod- und stat- Methoden.

from pathlib import Path


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