[SOLVED] I am trying to write a very simple recursive bash script to chmod 644 all files and chmod 755 all directories in a given directory
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I am not sure if changing file permissions twice has more overhead than processing them once but spawning one more process (find). It is, however, definitely less to type and there should not be much difference in execution time on a reasonably modern machine.
there goes all of my scripts in ~/bin got a redo them now to make them exec again. that entire recursive in my current dir if its home dir look out.
I am not sure if changing file permissions twice has more overhead than processing them once but spawning one more process (find). It is, however, definitely less to type and there should not be much difference in execution time on a reasonably modern machine.
Its worth pointing out that some older versions of GNU find do not have this, that probably doesn't matter in practice for most people.
strips the path, showing the bare filenames. You would need to "cd" into it, giving you some other problems.
The following is much more elegant
Code:
#! /bin/bash
DIR=$1
if [[ ! -d $DIR ]]
then
echo "
$0 command accepts one directory as an argument, any further arguments are
ignored. You have passed something other than a directory for arg 1, please try again.
Perhaps check your spelling. Also, at least one argument must be passed in.
"
exit 1
fi
# ls "$DIR" strips the path
# option nullglob: return nothing if nothing matches in filename glob
# option dotglob: include filenames starting with a dot (like ls -A)
shopt -s nullglob dotglob
recurse(){
chmod 755 "$1"
for ITEM in "$1"/*
do
[[ -h $ITEM ]] && continue
if [[ -f $ITEM ]]
then
chmod 644 "$ITEM"
elif [[ -d $ITEM ]]
then
recurse "$ITEM"
fi
done
}
recurse "$DIR"
echo "
New permissions are as follows:
"
ls -lR "$DIR"
Thanks so much for clearing that up, I changed my script piece by piece. First adding the wildcard to the -- $(ls $1) -- to make it -- $(ls $1/*) --, but it still did not work so I removed the ls making the line -- for Item in "$1"/* -- which resulted in a successful recursion of the directory tree passed in.
From reading in -- man bash -- I see the clever use of the "-h" option paired with "continue". If I understand correctly:
Code:
[[ -h $ITEM ]] && continue
is equivalent to:
Code:
if [[ -h $ITEM ]]
then
continue
fi
if bash is like Java in that when doubling the -- & -- with -- && --, the second expression is not checked unless the first is false. In bash though, the single -- & -- puts a command in the background right? So I am guessing that is just the default behavior of compound expressions, unlike in Java where when using a single -- & -- the next expression is checked regardless of the true or false condition of the preceding expression ...I could be remembering that incorrectly since I only ever use the double -- && --.
Quote:
Only the function is recursive; the overhead is much smaller compared to calling the whole script.
thanks, using the function seems a better option overall, I actually abandoned the recursive script and stuck with the recursive function in a script.
Quote:
Using nullglob we can emulate an ls that does not strip the path.
Using dotglob we can emulate an ls -A (find filenames that start with a dot).
Using a glob, we cannot disable filename globbing with set -f, so we should consequently put quotes around $var in command arguments. (Note: unlike [ ], the [[ ]] is not a command. Of course you could put quotes neverheless.)
And, last but not least, do not follow symlinks! -f/-d is true if it's a file/directory or a symlink to a file/directory.
Reading in -- man bash -- I get that -- shopt -s -- enables options and that the dotglob option causes the dot files to be included in the output of -- "$1"/* --, I think. What I am not quite getting is the nullglob option:
Quote:
quoted from bash man page:
"nullglob
If set, bash allows patterns which match no files (see Pathname Expansion above) to expand to
a null string, rather than themselves."
"Pathname Expansion
If no matching filenames
are found, and the shell option nullglob is not enabled, the word is left unchanged. If the nullglob option
is set, and no matches are found, the word is removed."
So, in this script, does enabling nullglob cause an empty directory's name to be removed from the iteration list, during iteration, in the for loop? I have not added the line -- shopt -s nullglob dotglob -- to my script yet, since I do not yet understand it and do not wish to write code I do not yet understand, and the script works as I intended. What does this line do, especially where nullglob is concerned, and am I understanding what dotglob is doing correctly?
and still get the same effect, I was mealy pointing out the dot being current dir, so if in /home/user what effects can one expect, regardless if one copy paste that, or types it in. Not everyone that may read this know what that dot is for.
mkdir temp
cd temp
echo "ls output:"
ls
echo "for loop output:"
for i in *
do
echo "$i"
done
You’ll see that a "no match" becomes the search term "*", and the loop runs once with it.
With option nullglob a "no match" becomes a nullstring, and the loop does not run.
An exercise for dotglob:
Code:
mkdir temp
cd temp
touch file1 file2 .file3
echo "ls output:"
ls
echo "ls -A output:"
la -A
echo "for loop output:"
for i in *
do
echo "$i"
done
You‘ll see that filenames starting with a dot are "hidden" by default.
With option dotglob they are treated like normal filenames i.e. the "*" shows them, just like "ls -A" does.
and still get the same effect, I was mealy pointing out the dot being current dir, so if in /home/user what effects can one expect, regardless if one copy paste that, or types it in. Not everyone that may read this know what that dot is for.
There are a number of ways to avoid that. In GNU find "-mindepth 1" will do the job (but I believe that's a GNU extension). You could add ! -name "." to achieve the same thing. Alternatively, for a more complex example, if you wanted to only list the files that are not hidden and which are not in hidden directories you can do: find . -type d -name ".?*" -prune -o -type f ! -name ".*" -print
That last one's useful when you're in your home dir, or a git working directory.
Anyway, the take home is that find is a very powerful but subtle tool. Well worth learning but you definitely need to be careful with it.
I have seen several responses on the links in answer #5 that are similar to this, however, on my system at least, this sort of use of "chmod -R" gives execute privileges to all files as well as directories. It seems that whatever means are used to determine where X makes sense are not working in such a way as to be useful here.
I think this is why:
Quote:
quoted from the chmod man page:
execute/search only if the file is a directory or already has execute permission for some user (X)
Last edited by Astral Axiom; 05-31-2019 at 09:19 AM.
Reason: edited to: answer #5
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.