Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

This has been discussed before here.

What I'd like to know is how to turn these:

Recursive chmod only files within this folder:

find . -type f -exec chmod 0600 {} \;

Recursive chmod only folders within this folder:

find . -type d -exec chmod 0755 {} \;

into a bash script, so it could be something like:

For files:

rchmodf 744 .

For directories:

rchmodd 755 .

and... also maybe into a nautilus right click menu option if that's possible.

share|improve this question

3 Answers 3

up vote 9 down vote accepted

Here's a script you can call by passing the mode as the first argument and one or more directory names as subsequent arguments. Under Linux, if you don't pass any directory name, it'll be as though you passed . (the current directory). Name this script rchmodf, make it executable (chmod a+rx /path/to/rchmodf) and put it somewhere on your $PATH.

#!/bin/sh
mode=$1; shift
find "$@" -type f -exec chmod "$mode" {} +

Explanations: mode=$1; shift sets the variable mode to the first argument of the script and removes that first argument from the list. "$@" expands to the list of all arguments.

If you like, you can make a script that accepts both a directory mode and a file mode.

#!/bin/sh
dir_mode=$1; shift
file_mode=$1; shift
find "$@" -type d -exec chmod "$dir_mode" {} + -o -type f -exec chmod "$file_mode" {} +

Note that 744 isn't a useful file mode; 644 (user-writable and world-readable) and 755 (also world-executable) are much more common. Also, changing every file in a tree to be executable or not to be executable is rarely useful; you'll probably want to call this script with arguments like +rX (capital X, to set the executable bit only for directories and for files that are already executable). In fact, the X symbolic mode is probably what you were after with these scripts: chmod -R +rX ..

With bash or zsh, there's another way to act recursively but on directories only. For bash, you need version 4 and to run shopt -s globstar first.

chmod a+rx **/*/

In zsh, you can act on files only by suffixing (.): chmod a+r **/*(.).

I'll pass on the Nautilus question.

share|improve this answer
    
Ninjas an nincompoops! You can use one find to execute different commands on different result sets? +1 for overloading the OR operator. –  Caleb Jun 11 '11 at 7:52

I wrote a script that basically does the above but also provides a bit of flexibility for command line options (directory and/or file permissions, or exclude both it automatically resets everything to 755-644). It also checks for a few error scenarios.

http://bigfloppydonkeydisk.blogspot.com.au/2012/09/recursively-chmod-only-files-or.html

Hope it helps!

share|improve this answer
2  
You should paste the code here. That way, we avoid lots of dead links in the future. If you're worried about the two versions drifting apart, you can still leave the link there for reference. –  l0b0 Sep 22 '12 at 8:50

Script linked to by user23538, hope you don't mind.

I have tried it and it works well. Please note that if you use . as the path argument (run it in the same directory where the script is located), it does in fact change the scripts own file permissions to 644, so put it in the directory above.

#!/bin/sh
#
# chmodr.sh
#
# author: Francis Byrne
# date: 2011/02/12
#
# Generic Script for recursively setting permissions for directories and files
# to defined or default permissions using chmod.
#
# Takes a path to recurse through and options for specifying directory and/or
# file permissions.
# Outputs a list of affected directories and files.
#
# If no options are specified, it recursively resets all directory and file
# permissions to the default for most OSs (dirs: 755, files: 644).

# Usage message
usage()
{
echo "Usage: $0 PATH -d DIRPERMS -f FILEPERMS"
echo "Arguments:"
echo "PATH: path to the root directory you wish to modify permissions for"
echo "Options:"
echo " -d DIRPERMS, directory permissions"
echo " -f FILEPERMS, file permissions"
exit 1
}

# Check if user entered arguments
if [ $# -lt 1 ] ; then
usage
fi

# Get options
while getopts d:f: opt
do
case "$opt" in
d) DIRPERMS="$OPTARG";;
f) FILEPERMS="$OPTARG";;
\?) usage;;
esac
done

# Shift option index so that $1 now refers to the first argument
shift $(($OPTIND - 1))

# Default directory and file permissions, if not set on command line
if [ -z "$DIRPERMS" ] && [ -z "$FILEPERMS" ] ; then
DIRPERMS=755
FILEPERMS=644
fi

# Set the root path to be the argument entered by the user
ROOT=$1

# Check if the root path is a valid directory
if [ ! -d $ROOT ] ; then
echo "$ROOT does not exist or isn't a directory!" ; exit 1
fi

# Recursively set directory/file permissions based on the permission variables
if [ -n "$DIRPERMS" ] ; then
find $ROOT -type d -print0 | xargs -0 chmod -v $DIRPERMS
fi

if [ -n "$FILEPERMS" ] ; then
find $ROOT -type f -print0 | xargs -0 chmod -v $FILEPERMS
fi
share|improve this answer
    
@user23538 was already instructed to paste the code in a block on-site. You should not then post exactly that unless you have something more to add. –  HalosGhost Jun 25 at 18:16
    
They were instructed to, but they didn't. So I did. That is what was requested, even if I'm not the same person. Please explain why this is incorrect? –  Kluny Jun 25 at 18:49
    
Ahh, I missed how long ago the user had posted their answer. If you find something about your answer to edit, I will be happy to remove my down-vote. –  HalosGhost Jun 25 at 18:51
    
Thank you, I added a note that I've tested the script. –  Kluny Jun 25 at 18:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.