Як зробити простий "chmod + x" зсередини python?


119

Я хочу створити файл із сценарію python, який виконується.

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

Схоже os.chmod, не "додає" дозволи, як chmodце робить Unix . Після останнього прокоментованого рядка у файлі є режим файлу -rw-r--r--, при цьому він не коментується, режим файлу є ---x------. Як я можу просто додати u+xпрапор, зберігаючи інші режими недоторканими?

Відповіді:


197

Використовуйте os.stat()для отримання поточних дозволів, використання |для або бітів разом, і використовуйте os.chmod()для встановлення оновлених дозволів.

Приклад:

import os
import stat

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

2
Це робить його виконуваним лише користувачем. Плакат запитував про "chmod + x", що робить його виконуваним на всій дошці (користувач, група, світ)
eric.frederich

35
Використовуйте наступне, щоб зробити його виконаним усіма ... stat.S_IXUSR | stat.S_IXGRP | стат.S_IXOTH. Зауважте: це значення те саме, що і вісімковий 0111, тому ви можете просто зробити st.st_mode | 0111
eric.frederich

1
Моя відповідь нижче копіює біти R на X, як можна було б очікувати від скажу, компілятора.
Джонатан Райнхарт

Я б робив STAT_OWNER_EXECUTABLE = stat.S_IEXECі використовував людську читану локальну константу замість гнучкої.
ThorSummoner

ось непітонічна відповідь, яка може бути трохи читабельнішою: subprocess.check_call(['chmod', '+x', 'somefile'])і давайте легше робити такі операції, як a+rx.
Тревор Бойд Сміт

20

Для інструментів, що генерують виконувані файли (наприклад, скрипти), може бути корисний наступний код:

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

Це змушує (більш-менш) поважати те, umaskщо діяло під час створення файлу: Виконавчий файл встановлюється лише для тих, хто може читати.

Використання:

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
Восьмі літерали змінилися в Python 3. Замість цього 0444ви використовували б 0o444. Або, якщо ви хочете підтримати обоє, просто напишіть 292.
Кевін

1
@Kevin Схоже, що новий синтаксис підтримується Python 2.6, тому представляється розумним використовувати це. (Для контрольної точки сумісності CentOS 6 постачається з Python 2.6).
Джонатан Райнхарт

2
Мені не було відомо, що Python 3 видалив традиційні восьмеричні букви. Тож дякую за це.
Джонатан Райнхарт

12

Якщо ви знаєте потрібні дозволи, то наступний приклад може бути способом спростити це.

Пітон 2:

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

Пітон 3:

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

Сумісний з будь-яким (восьмиденне перетворення):

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

приклади довідкових дозволів


4
Це повинно бути os.chmod ("/ somedir / somefile", 0o775)
англ.

4

Ви також можете це зробити

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

Поточний список файлу

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

Тепер зробіть це.

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

і ви побачите це в терміналі.

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

Ви можете побіжно або з 0o111 зробити все виконуваним, 0o222 зробити все для запису, а 0o444 зробити все читабельним.


2

Поважайте umaskякchmod +x

man chmodкаже, що якщо augoне вказано як у:

chmod +x mypath

потім aвикористовується, але з umask:

Комбінація букв ugoa визначає, яким чином буде змінено доступ користувачів до файлу: користувача, якому належить (u), інших користувачів у групі файлу (g), інших користувачів, які не належать до групи файлів (o), або всіх користувачів (а). Якщо нічого з цього не наводиться, ефект є таким, як якщо б (а) було надано, але біти, встановлені в умасці, не впливають.

Ось версія, яка точно моделює таку поведінку:

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

Дивіться також: Як я можу отримати дозволи файлу за замовчуванням у Python?

Тестовано в Ubuntu 16.04, Python 3.5.2.


1

У python3:

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

Не забудьте додати 0oпрефікс, оскільки дозволи встановлені як вісімкове ціле число, і Python автоматично розглядає будь-яке ціле число з провідним нулем як вісімкове. Інакше ви проходите os.chmod("somefile", 1230)дійсно, що дорівнює восьмери 664.


1
Це встановлює дозволи на абсолютне значення, воно не робить chmod +запит ОП, який повинен додавати нові дозволи до існуючих.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

0

Якщо ви використовуєте Python 3.4+, ви можете використовувати зручну траєкторію стандартної бібліотеки .

Його шлях класу має вбудований CHMOD і стат методів.

from pathlib import Path


f = Path("/path/to/file.txt")
f.chmod(f.stat().st_mode | stat.S_IEXEC)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.