Determining Whether a Directory is Writeable

前端 未结 10 1910
萌比男神i
萌比男神i 2020-12-07 14:44

What would be the best way in Python to determine whether a directory is writeable for the user executing the script? Since this will likely involve using the os module I sh

相关标签:
10条回答
  • 2020-12-07 15:07

    I ran into this same need while adding an argument via argparse. The built in type=FileType('w') wouldn't work for me as I was looking for a directory. I ended up writing my own method to solve my problem. Here is the result with argparse snippet.

    #! /usr/bin/env python
    import os
    import argparse
    
    def writable_dir(dir):
        if os.access(dir, os.W_OK) and os.path.isdir(dir):
            return os.path.abspath(dir)
        else:
            raise argparse.ArgumentTypeError(dir + " is not writable or does not exist.")
    
    parser = argparse.ArgumentParser()
    parser.add_argument("-d","--dir", type=writable_dir(), default='/tmp/',
        help="Directory to use. Default: /tmp")
    opts = parser.parse_args()
    

    That results in the following:

    $ python dir-test.py -h
    usage: dir-test.py [-h] [-d DIR]
    
    optional arguments:
      -h, --help         show this help message and exit
      -d DIR, --dir DIR  Directory to use. Default: /tmp
    
    $ python dir-test.py -d /not/real
    usage: dir-test.py [-h] [-d DIR]
    dir-test.py: error: argument -d/--dir: /not/real is not writable or does not exist.
    
    $ python dir-test.py -d ~
    

    I went back and added print opts.dir to the end, and everything appears to be functioning as desired.

    0 讨论(0)
  • 2020-12-07 15:11

    Here is something I created based on ChristopheD's answer:

    import os
    
    def isWritable(directory):
        try:
            tmp_prefix = "write_tester";
            count = 0
            filename = os.path.join(directory, tmp_prefix)
            while(os.path.exists(filename)):
                filename = "{}.{}".format(os.path.join(directory, tmp_prefix),count)
                count = count + 1
            f = open(filename,"w")
            f.close()
            os.remove(filename)
            return True
        except Exception as e:
            #print "{}".format(e)
            return False
    
    directory = "c:\\"
    if (isWritable(directory)):
        print "directory is writable"
    else:
        print "directory is not writable"
    
    0 讨论(0)
  • 2020-12-07 15:12

    If you need to check the permission of another user (yes, I realize this contradicts the question, but may come in handy for someone), you can do it through the pwd module, and the directory's mode bits.

    Disclaimer - does not work on Windows, as it doesn't use the POSIX permissions model (and the pwd module is not available there), e.g. - solution only for *nix systems.

    Note that a directory has to have all the 3 bits set - Read, Write and eXecute.
    Ok, R is not an absolute must, but w/o it you cannot list the entries in the directory (so you have to know their names). Execute on the other hand is absolutely needed - w/o it the user cannot read the file's inodes; so even having W, without X files cannot be created or modified. More detailed explanation at this link.

    Finally, the modes are available in the stat module, their descriptions are in inode(7) man.

    Sample code how to check:

    import pwd
    import stat
    import os
    
    def check_user_dir(user, directory):
        dir_stat = os.stat(directory)
    
        user_id, group_id = pwd.getpwnam(user).pw_uid, pwd.getpwnam(user).pw_gid
        directory_mode = dir_stat[stat.ST_MODE]
    
        # use directory_mode as mask 
        if user_id == dir_stat[stat.ST_UID] and stat.S_IRWXU & directory_mode == stat.S_IRWXU:     # owner and has RWX
            return True
        elif group_id == dir_stat[stat.ST_GID] and stat.S_IRWXG & directory_mode == stat.S_IRWXG:  # in group & it has RWX
            return True
        elif stat.S_IRWXO & directory_mode == stat.S_IRWXO:                                        # everyone has RWX
            return True
    
        # no permissions
        return False
    
    0 讨论(0)
  • 2020-12-07 15:13

    Check the mode bits:

    def isWritable(name):
      uid = os.geteuid()
      gid = os.getegid()
      s = os.stat(dirname)
      mode = s[stat.ST_MODE]
      return (
         ((s[stat.ST_UID] == uid) and (mode & stat.S_IWUSR)) or
         ((s[stat.ST_GID] == gid) and (mode & stat.S_IWGRP)) or
         (mode & stat.S_IWOTH)
         )
    
    0 讨论(0)
提交回复
热议问题