6

I want to execute chmod 555 on all files and directories I get with the following command (it returns the directory test and all files and directories in it):

find ~/.config/google-chrome -type d -name test -exec find {} \;
1
  • Find traverses the file system hierarchy recursively. Executing find from find makes no sense. Not even ever. Commented Jul 26, 2013 at 9:38

4 Answers 4

8

In this very case, you can use chmod -R as per user26112's answer, but in the general case, you can do:

find ~/.config/google-chrome -type d -name test -exec sh -c '
  for i do
    find "$i" -exec chmod 555 {\} +
  done' sh {} +

The trick being to use a shell and use quoting (like {\} or {"}") so that the inner {} is not expanded by the outer find (accounting for those implementations of find that still expand {} even when it's only part of an argument).

GNU find 4.9.0 or newer also supports getting the list of files to work on from stdin as NUL delimited records, so you can do:

find -files0-from <(
    find ~/.config/google-chrome -type d -name test -print0
  ) -exec chmod 555 {} +

With older versions, you can do something similar using GNU xargs and sh to reorder the arguments:

xargs -r0a <(
    find ~/.config/google-chrome -type d -name test -print0
  ) sh -c 'exec find "$@" -exec chmod 555 {} +' sh

(<(...) is process substitution, a ksh feature also supported by zsh and bash, not to be confused with yash's process redirection).

4

You can use chmod's -R flag to change the permissions of the directory and all of the files and directories in the hierarchy beneath it.

find ~/.config/google-chrome -type d -name test -exec chmod -R 555 '{}' \;
0
3

If you really want two find -exec, try the following

find /etc -type f -exec sh -c 'find "$0" -exec echo {\} \;' {} \;

(that will just pass to echo command what find did find)

find /etc -type d -exec sh -c 'find "$0" -type f -exec echo "$0" {\} \;' {} \;

(some useful example: prints dir name and list of files in it)

With using sh -c you can also resolve issue with pipes in the find -exec clause, also notice that passed arguments to sh -c will start from $0 not from $1 as usually do with shell script.

3
  • 1
    That doesn't work with the GNU find (as usually found on Linux based systems as the OP mentions he's using) and some other find implementations, because those expand {} even when they're not on their own as a single argument. So in your case, the first find would expand both {}. You forgot the quotes around $0. Commented Jul 25, 2013 at 8:23
  • @Stephane Chazelas great, you're right! That is why I sometimes had to doublequote $0 parameters.. Escaping the internal closing } curly brace is very tricky and smart) didn't notice that.
    – rook
    Commented Jul 25, 2013 at 9:21
  • 1
    Note that you can avoid running one shell per directory, by using + instead of \; and a loop in the shell. I prefer not using $0 there because $0 is used for instance by the shell to display error messages which can cause confusion. Hence the extra sh argument to set $0 in the solution I gave. Commented Jul 25, 2013 at 12:20
1

You can also run this command. It will run on each directory, but the + argument to find will run the chmod with multiple "test" directories passed as arguments:

$ find ~/.config/google-chrome -type d -name test -exec chmod -R 555 '{}' +

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .