Using search results when directories have spaces in names

I am trying to change the permissions of all subdirectories by creating a simple bash loop for:

for dir in `find . -type d`; do chmod 755 "$dir"; done

however, he complains about non-existent directories. Just by printing out the directory names from the loop (replacing chmod 755 "$dir"with echo "$dir"), I decided that the problem occurs when the directory has spaces in its name. It happens that the loop forbreaks the results findon each line of a new line and .

I would like to somehow make it split the results only according to the new lines and ignore the spaces. Double quotes must ensure that the string reaches chmodas a single argument. How to change the splitting?

+5
source share
3 answers

The usual solution to this problem is:

find ... -print0 | xargs -0 ...

The argument -print0causes the output file names to be nul-terminated, and the -0/ argument -nullfor xargs tells it to read such a format.

So in your case ...

$ find . -type d -a -print0 | xargs -0 chmod 755

In fact, you do not need a shell loop.

+6
source

Here are some more options for your toolkit. If you have only one command to execute in groups of files / directories, you findcan do this directly:

find . -type d -exec chmod 755 {} +

If a command can only work in one file / directory at a time, use \;instead +for starting one for each item:

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

And if you need to do something complicated (i.e. a few commands), you can make a safe version of the loop:

while IFS= read -r -u3 -d $'\0' dir; do
    sudo chown gkudelis "$dir"
    chmod 755 "$dir"
    touch "$dir/.perms_reset"
done 3< <(find /tmp -type f -print0)

, (<(...)), ; bash -only, script #!/bin/bash, #!/bin/sh. , fd 3 stdin, , - stdin, . , ("$dir" ), . . BashFAQ # 020.

+4

Try doing this instead (using the built-in functions, bash --version> = 4 is required ):

shopt -s globstar
for dir in **/*/; do
    chmod 0755 "${dir%/}"
done
+1
source

All Articles