Bagaimana Anda melakukan "chmod + x" sederhana dari dalam python?

119

Saya ingin membuat file dari dalam skrip python yang dapat dieksekusi.

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

tampaknya os.chmodtidak 'menambahkan' izin seperti yang chmoddilakukan unix . Dengan baris terakhir dikomentari, file memiliki filemode -rw-r--r--, dengan itu tidak dikomentari, mode file adalah ---x------. Bagaimana saya bisa menambahkan u+xbendera sambil menjaga mode lainnya tetap utuh?

pendeta
sumber

Jawaban:

197

Gunakan os.stat()untuk mendapatkan izin saat ini, gunakan |untuk atau bit bersama-sama, dan gunakan os.chmod()untuk menyetel izin yang diperbarui.

Contoh:

import os
import stat

st = os.stat('somefile')
os.chmod('somefile', st.st_mode | stat.S_IEXEC)
Ignacio Vazquez-Abrams
sumber
2
Ini hanya membuatnya dapat dieksekusi oleh pengguna. Poster itu menanyakan tentang "chmod + x" yang membuatnya dapat dieksekusi di seluruh papan (pengguna, grup, dunia)
eric.frederich
35
Gunakan perintah berikut untuk membuatnya dapat dieksekusi oleh semua orang ... stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH. Catatan: nilai tersebut sama dengan oktal 0111, jadi anda dapat melakukan st.st_mode | 0111
eric.frederich
1
Jawaban saya di bawah ini menyalin bit R ke X, seperti yang diharapkan dari katakanlah, kompiler.
Jonathon Reinhart
Saya akan melakukannya STAT_OWNER_EXECUTABLE = stat.S_IEXEC, dan menggunakan konstanta lokal yang dapat dibaca manusia, bukan yang omong kosong.
ThorSummoner
berikut adalah jawaban non-pythonic yang mungkin sedikit lebih mudah dibaca: subprocess.check_call(['chmod', '+x', 'somefile'])dan membuat Anda lebih mudah melakukan operasi seperti a+rx.
Trevor Boyd Smith
20

Untuk alat yang menghasilkan file yang dapat dieksekusi (misalnya skrip), kode berikut mungkin berguna:

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

Ini membuatnya (lebih atau kurang) menghormati umaskyang berlaku saat file dibuat: Executable hanya disetel untuk mereka yang bisa membaca.

Pemakaian:

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
sumber
2
Literal oktal diubah dalam Python 3. Sebagai ganti 0444, Anda akan menggunakan 0o444. Atau, jika ingin mendukung keduanya, tulis saja 292.
Kevin
1
@Kevin Sepertinya sintaks baru telah didukung oleh Python 2.6, jadi sepertinya masuk akal untuk menggunakannya. (Untuk titik referensi kompatibilitas, CentOS 6 dikirimkan dengan Python 2.6).
Jonathon Reinhart
2
Saya tidak menyadari bahwa Python 3 telah menghapus literal oktal tradisional. Jadi terimakasih untuk itu.
Jonathon Reinhart
13

Jika Anda mengetahui izin yang Anda inginkan, contoh berikut mungkin cara untuk membuatnya tetap sederhana.

Python 2:

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

Python 3:

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

Kompatibel dengan (konversi oktal):

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

contoh izin referensi

zerocog
sumber
4
Ini harus os.chmod ("/ somedir / somefile", 0o775)
dan bulan
4

Anda juga bisa melakukan ini

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

Daftar file saat ini

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

Sekarang lakukan ini.

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

dan Anda akan melihat ini di terminal.

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

Anda dapat menggunakan bitwise atau dengan 0o111 untuk membuat semua dapat dieksekusi, 0o222 untuk membuat semua dapat ditulis, dan 0o444 untuk membuat semua dapat dibaca.

ncmathsadist.dll
sumber
2

Hormati umasksepertichmod +x

man chmodmengatakan bahwa jika augotidak diberikan seperti pada:

chmod +x mypath

kemudian adigunakan tetapi dengan umask:

Kombinasi huruf ugoa mengontrol akses pengguna ke file mana yang akan diubah: pengguna yang memilikinya (u), pengguna lain di grup file (g), pengguna lain yang tidak ada di grup file (o), atau semua pengguna (a). Jika tidak ada yang diberikan, efeknya seolah-olah (a) diberikan, tetapi bit yang disetel dalam umask tidak terpengaruh.

Berikut adalah versi yang mensimulasikan perilaku itu dengan tepat:

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

Lihat juga: Bagaimana saya bisa mendapatkan izin file default dengan Python?

Diuji di Ubuntu 16.04, Python 3.5.2.

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

Di python3:

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

Ingatlah untuk menambahkan 0oawalan karena izin ditetapkan sebagai bilangan bulat oktal, dan Python secara otomatis memperlakukan bilangan bulat apa pun dengan nol di depannya sebagai oktal. Jika tidak, Anda os.chmod("somefile", 1230)memang melewati , yaitu oktal 664.

funkid
sumber
1
Ini tidak mengatur izin ke nilai absolut, itu tidak melakukan chmod +seperti yang diminta oleh OP, yang harus menambahkan izin baru ke yang sudah ada.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
0

Jika Anda menggunakan Python 3.4+, Anda dapat menggunakan pathlib perpustakaan standar yang nyaman .

Its Jalur kelas telah built-in chmod dan Stat metode.

from pathlib import Path


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