【问题标题】:How do you do a simple "chmod +x" from within python?你如何在 python 中做一个简单的“chmod +x”?
【发布时间】:2012-09-29 07:26:33
【问题描述】:

我想从一个可执行的 python 脚本中创建一个文件。

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

看来os.chmod 不像unix chmod 那样“添加”权限。注释掉最后一行,文件的文件模式为-rw-r--r--,没有注释掉,文件模式为---x------。如何在保持其余模式不变的同时添加 u+x 标志?

【问题讨论】:

  • 你们中有多少人来这里研究相同的解决方案,但对于 golang ?

标签: python chmod


【解决方案1】:

使用os.stat()获取当前权限,使用|对位进行OR运算,使用os.chmod()设置更新后的权限。

例子:

import os
import stat

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

【讨论】:

  • 这只能让用户执行它。发帖人问的是“chmod +x”,这使得它可以全面执行(用户、组、世界)
  • 使用以下命令使其对所有人都可执行... stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH。注意:该值与八进制 0111 相同,因此您只需执行 st.st_mode | 0111
  • My answer below 将 R 位复制到 X,正如人们对编译器所期望的那样。
  • 我会做STAT_OWNER_EXECUTABLE = stat.S_IEXEC,并使用人类可读的本地常量而不是乱码。
  • 这是一个非pythonic的答案,可能更具可读性:subprocess.check_call(['chmod', '+x', 'somefile']),让您更轻松地进行a+rx之类的操作。
【解决方案2】:

对于生成可执行文件的工具(例如脚本),以下代码可能会有所帮助:

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)

【讨论】:

  • 在 Python 3 中更改了八进制文字。您可以使用 0o444 而不是 0444。或者,如果您想同时支持两者,只需写 292
  • @Kevin It looks like Python 2.6 已支持新语法,因此使用它似乎是合理的。 (作为兼容性参考点,CentOS 6 附带 Python 2.6)。
  • 我不知道 Python 3 已经删除了传统的八进制文字。所以谢谢你。
【解决方案3】:

如果你知道你想要的权限,那么下面的例子可能是保持简单的方法。

Python 2:

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

Python 3:

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

兼容任一(八进制转换):

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

参考permissions examples

【讨论】:

  • 这应该是 os.chmod("/somedir/somefile", 0o775)
【解决方案4】:

如果您使用的是 Python 3.4+,则可以使用标准库方便的pathlib

它的Path 类具有内置的chmodstat 方法。

from pathlib import Path
import stat


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

【讨论】:

  • 没有import stat就不行
【解决方案5】:

尊重umask就像chmod +x

man chmod 表示如果augo 没有给出如下:

chmod +x mypath

然后使用a,但使用umask

字母 ugoa 的组合控制哪些用户对文件的访问权限将被更改:拥有它的用户 (u)、文件组中的其他用户 (g)、不在文件组中的其他用户 (o) ,或所有用户 (a)。如果这些都没有给出,效果就像给出 (a) 一样,但在 umask 中设置的位不受影响。

这样做的目的是让您不会意外授予太多权限。 umask 确定新文件的默认权限,例如使用0077 的umask,touch newfile.txt 为当前用户生成权限rw,因为77 将排除组和其他(尽管默认情况下不会通过触摸给出x)。并且chmod +x 同样只会为用户添加+x,忽略组和其他由于0011 部分的掩码:你需要chmod o+xchmod g+xchmod go+xchmod a+x 来强制它们设置。

这是一个完全模拟该行为的版本:

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

另请参阅:How can I get the default file permissions in Python?

在 Ubuntu 16.04、Python 3.5.2 中测试。

【讨论】:

    【解决方案6】:

    你也可以这样做

    >>> 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 使所有文件可读。

    【讨论】:

      【解决方案7】:

      在python3中:

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

      请记住添加0o 前缀,因为权限设置为八进制整数,Python 会自动将任何以零开头的整数视为八进制。否则,您确实传递了os.chmod("somefile", 1230),它是664 的八进制。

      【讨论】:

      • 这确实将权限设置为绝对值,它不会按照 OP 的要求执行 chmod +,它应该向现有权限添加新权限。
      猜你喜欢
      • 2013-04-27
      • 1970-01-01
      • 1970-01-01
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多