Làm thế nào để bạn thực hiện một “chmod + x” đơn giản từ bên trong python?


119

Tôi muốn tạo một tệp từ bên trong một tập lệnh python có thể thực thi được.

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

nó dường os.chmodnhư không 'thêm' quyền như cách unix chmodlàm. Với dòng cuối cùng được chú thích, tệp có mã tệp -rw-r--r--, với nó không được chú thích, chế độ tệp là ---x------. Làm cách nào để tôi vừa thêm u+xcờ vừa giữ nguyên các chế độ còn lại?

Câu trả lời:


197

Sử dụng os.stat()để nhận các quyền hiện tại, sử dụng |hoặc các bit với nhau và sử dụng os.chmod()để đặt các quyền đã cập nhật.

Thí dụ:

import os
import stat

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

2
Điều này chỉ làm cho nó có thể thực thi được bởi người dùng. Các tấm áp phích được hỏi về "chmod + x" mà làm cho nó thực thi trên bảng (user, group, thế giới)
eric.frederich

35
Sử dụng phần sau để mọi người có thể thực thi được ... stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH. Lưu ý: giá trị đó giống với bát phân 0111, vì vậy bạn chỉ có thể thực hiện st.st_mode | 0111
eric.frederich

1
Câu trả lời của tôi dưới đây sao chép các bit R sang X, như người ta mong đợi từ một trình biên dịch.
Jonathon Reinhart

Tôi sẽ làm STAT_OWNER_EXECUTABLE = stat.S_IEXECvà sử dụng hằng số cục bộ có thể đọc được của con người thay vì hằng số vô nghĩa.
ThorSummoner

đây là một câu trả lời không phải pythonic có thể dễ đọc hơn một chút: subprocess.check_call(['chmod', '+x', 'somefile'])và cho phép bạn dễ dàng thực hiện các thao tác như a+rx.
Trevor Boyd Smith

20

Đối với các công cụ tạo tệp thực thi (ví dụ: tập lệnh), đoạn mã sau có thể hữu ích:

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

Điều này làm cho nó (ít nhiều) tôn trọng umaskhiệu lực khi tệp được tạo: Executable chỉ được đặt cho những tệp có thể đọc.

Sử dụng:

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
Các ký tự bát phân đã thay đổi trong Python 3. Thay vì 0444, bạn sẽ sử dụng 0o444. Hoặc, nếu bạn muốn hỗ trợ cả hai, chỉ cần viết 292.
Kevin

1
@Kevin Có vẻ như cú pháp mới đã được Python 2.6 hỗ trợ, vì vậy có vẻ hợp lý khi sử dụng nó. (Đối với điểm tham chiếu tương thích, CentOS 6 đi kèm với Python 2.6).
Jonathon Reinhart

2
Tôi không biết rằng Python 3 đã loại bỏ các ký tự bát phân truyền thống. Vì vậy, cảm ơn bạn vì điều đó.
Jonathon Reinhart

13

Nếu bạn biết các quyền bạn muốn thì ví dụ sau có thể là cách để giữ cho nó đơn giản.

Python 2:

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

Python 3:

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

Tương thích với một trong hai (chuyển đổi bát phân):

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

tham chiếu các ví dụ về quyền


4
Đây phải là os.chmod ("/ somedir / somefile", 0o775)
ang mo

4

Bạn cũng có thể làm điều này

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

Danh sách hiện tại của tệp

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

Bây giờ làm điều này.

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

và bạn sẽ thấy điều này trong thiết bị đầu cuối.

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

Bạn có thể bitwise hoặc với 0o111 để làm cho tất cả có thể thực thi được, 0o222 để làm cho tất cả có thể ghi và 0o444 để làm cho tất cả có thể đọc được.


2

Tôn trọng umasknhưchmod +x

man chmodnói rằng nếu augokhông được đưa ra như trong:

chmod +x mypath

sau đó ađược sử dụng nhưng với umask:

Tổ hợp các chữ cái ugoa kiểm soát quyền truy cập của người dùng vào tệp sẽ bị thay đổi: người dùng sở hữu nó (u), những người dùng khác trong nhóm của tệp (g), những người dùng khác không thuộc nhóm của tệp (o) hoặc tất cả người dùng (a). Nếu không có cái nào trong số này được đưa ra, hiệu ứng giống như (a) được đưa ra, nhưng các bit được đặt trong umask không bị ảnh hưởng.

Đây là phiên bản mô phỏng chính xác hành vi đó:

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

Xem thêm: Làm cách nào để nhận quyền truy cập tệp mặc định trong Python?

Đã thử nghiệm trong Ubuntu 16.04, Python 3.5.2.


1

Trong python3:

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

Hãy nhớ thêm 0otiền tố vì quyền được đặt dưới dạng số nguyên bát phân và Python tự động xử lý bất kỳ số nguyên nào có số 0 đứng đầu là số bát phân. Nếu không, bạn đang os.chmod("somefile", 1230)thực sự vượt qua , là bát phân của 664.


1
Điều này đặt quyền thành một giá trị tuyệt đối, nó không thực hiện chmod +như yêu cầu của OP, điều này sẽ thêm các quyền mới vào các quyền hiện có.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

0

Nếu bạn đang sử dụng Python 3.4 trở lên, bạn có thể sử dụng thuận tiện các thư viện chuẩn của pathlib .

Lớp Path của nó có các phương thức chmodstat được tích hợp sẵn .

from pathlib import Path


f = Path("/path/to/file.txt")
f.chmod(f.stat().st_mode | stat.S_IEXEC)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.