Come si fa un semplice "chmod + x" da Python?


119

Voglio creare un file da uno script Python che sia eseguibile.

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

sembra os.chmodche non "aggiunga" le autorizzazioni come chmodfa Unix . Con l'ultima riga commentata, il file ha la modalità file -rw-r--r--, con non commentata, la modalità file è ---x------. Come posso semplicemente aggiungere la u+xbandiera mantenendo intatte le altre modalità?

Risposte:


197

Utilizzare os.stat()per ottenere le autorizzazioni correnti, utilizzare |o i bit insieme e utilizzare os.chmod()per impostare le autorizzazioni aggiornate.

Esempio:

import os
import stat

st = os.stat('somefile')
os.chmod('somefile', st.st_mode | stat.S_IEXEC)

2
Questo lo rende eseguibile solo dall'utente. Il poster chiedeva di "chmod + x" che lo rende eseguibile su tutta la linea (utente, gruppo, mondo)
eric.frederich

35
Usa quanto segue per renderlo eseguibile da tutti ... stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH. Nota: quel valore è lo stesso dell'ottale 0111, quindi potresti semplicemente fare st.st_mode | 0111
eric.frederich

1
La mia risposta di seguito copia i bit R su X, come ci si aspetterebbe da un compilatore.
Jonathon Reinhart

Lo farei STAT_OWNER_EXECUTABLE = stat.S_IEXECe userei la costante locale leggibile dall'uomo invece di quella senza senso.
ThorSummoner

ecco una risposta non pitonica che potrebbe essere un po 'più leggibile: subprocess.check_call(['chmod', '+x', 'somefile'])e ti consente di eseguire più facilmente operazioni come a+rx.
Trevor Boyd Smith il

20

Per gli strumenti che generano file eseguibili (ad es. Script), il codice seguente potrebbe essere utile:

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

Questo fa sì che rispetti (più o meno) quello umaskche era in vigore al momento della creazione del file: eseguibile è impostato solo per quelli che possono leggere.

Uso:

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)

2
I letterali ottali sono stati modificati in Python 3. Invece di 0444, useresti 0o444. Oppure, se vuoi supportare entrambi, scrivi 292.
Kevin

1
@Kevin Sembra che la nuova sintassi sia stata supportata da Python 2.6, quindi sembra ragionevole usarla. (Per un punto di riferimento sulla compatibilità, CentOS 6 viene fornito con Python 2.6).
Jonathon Reinhart

2
Non sapevo che Python 3 avesse rimosso i tradizionali letterali ottali. Quindi grazie.
Jonathon Reinhart

13

Se conosci le autorizzazioni che desideri, il seguente esempio potrebbe essere il modo per mantenerlo semplice.

Python 2:

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

Python 3:

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

Compatibile con entrambi (conversione ottale):

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

esempi di autorizzazioni di riferimento


4
Dovrebbe essere os.chmod ("/ somedir / somefile", 0o775)
ang il

4

Puoi anche farlo

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

Elenco corrente del file

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

Adesso fallo.

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

e lo vedrai nel terminale.

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

Puoi bit a bit o con 0o111 per rendere tutto eseguibile, 0o222 per rendere tutto scrivibile e 0o444 per renderlo leggibile.


2

Rispetto umaskcomechmod +x

man chmoddice che se augonon è dato come in:

chmod +x mypath

quindi aviene utilizzato ma con umask:

Una combinazione delle lettere ugoa controlla quale accesso degli utenti al file verrà modificato: l'utente che lo possiede (u), altri utenti nel gruppo del file (g), altri utenti non nel gruppo del file (o) o tutti utenti (a). Se nessuno di questi viene fornito, l'effetto è come se fosse stato fornito (a), ma i bit impostati nell'umask non sono influenzati.

Ecco una versione che simula esattamente quel comportamento:

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

Vedi anche: Come posso ottenere i permessi dei file predefiniti in Python?

Testato in Ubuntu 16.04, Python 3.5.2.


1

In python3:

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

Ricorda di aggiungere il 0oprefisso poiché i permessi sono impostati come un numero intero ottale e Python tratta automaticamente qualsiasi numero intero con uno zero iniziale come ottale. Altrimenti, stai os.chmod("somefile", 1230)davvero passando , che è ottale di 664.


1
Questo imposta i permessi su un valore assoluto, non fa chmod +come richiesto da OP, che dovrebbe aggiungere nuovi permessi a quelli esistenti.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

0

Se stai usando Python 3.4+, puoi usare la comoda pathlib della libreria standard .

La sua classe Path ha metodi chmod e stat incorporati .

from pathlib import Path


f = Path("/path/to/file.txt")
f.chmod(f.stat().st_mode | stat.S_IEXEC)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.