This is similar to using the Unix find command to recursively set directory permissions. Often you want to do this to make sure that permissions on all directories under a given path are set to a specific value.
find /var/www/html -type d -exec chmod 750 {} \;
Today I decided I wanted to do it in Python. I created the following interactive script which takes two arguments: the path and the permission mode. For example it can be run like:
chmoddirs /var/www/html 750
If the user enters invalid data it will print a message and quit. If the data is valid then it asks for a confirmation before executing.
#!/usr/bin/python3
import sys, os, re
# if 2 arguments not supplied print usage summary and exit
if len(sys.argv) != 3:
print("Usage: chmoddirs <path> <mode>")
print("Where <mode> is similar to '755', '0755', etc.")
exit()
# Create regex for string representing valid permission modes,
# octal values 0-7, optional 4th bit field
validModes = re.compile("^[0-7][0-7][0-7][0-7]?$")
pathErrorMsg = ""
modeErrorMsg = ""
# Check if argv[1] is a valid directory
# ToDo: check to see if we actually have permission to chmod
if not os.path.isdir(sys.argv[1]):
pathErrorMsg = "Invalid argument: '" + sys.argv[1] + "' is not a directory"
# Check if argv[2] is a valid mode
if not validModes.match(sys.argv[2]):
modeErrorMsg = "Invalid argument: Invalid mode: '" + sys.argv[2] + "'"
# Display error messages
# Both path and mode are invalid
if pathErrorMsg != "" and modeErrorMsg != "":
print(pathErrorMsg + "\n" + modeErrorMsg)
exit()
# Path is invalid
elif pathErrorMsg != "":
print(pathErrorMsg)
exit()
# Mode is invalid
elif modeErrorMsg != "":
print(modeErrorMsg)
exit()
# Prompt for confirmation
print("Changing permissions for all directories under", sys.argv[1],
"to", sys.argv[2])
userResponse = input('Proceed? (y/N)')
while userResponse not in ['y', 'Y', 'n', 'N']:
if userResponse == "":
exit()
print("Invalid choice")
print("Changing permissions for all directories under", sys.argv[1],
"to", sys.argv[2])
userResponse = input('Proceed? (y/N)')
# User does not confirm
if userResponse not in ['y', 'Y']:
exit()
# User confirms, perform operation
else:
# Cast argv[2] string to octal for os.chmod()
mode = int(sys.argv[2], 8)
for root, dirs, files in os.walk(sys.argv[1], topdown=True):
for dir in dirs:
os.chmod(os.path.join(root, dir), mode)
Leave a Reply
You must be logged in to post a comment.