1

I see a few requests that are similar to mine using the prune action, but what I want to do is recursively navigate through a docroot:

/opt/web

which contains several files and directories:

/opt/web/foo.html     (file)
/opt/web/bar.txt      (file)
/opt/web/DONOTCHGRP   (dir)
/opt/web/assets       (dir)

I want to go through the whole docroot and if any files are not group owned by "mygroup" then change the group to "mygroup" and set the group write permission bit, except completely ignore the DONOTCHGRP directory itself and its contents.

I currently have the command to do the chgrp/chmod with no filtering on anything:

find /opt/web -not -group mygroup |
    xargs -I {} sh -c '{ chmod g+w {}; chgrp mygroup {};}'

I just can't figure out how to completely skip the DONOTCHGRP directory. Any help will be appreciated.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • One option, not necessarily the best, is to first run an unrestricted change group and then a second one the undoes the prior change group on the one that needs to be unchanged in the long run. Whether this is sensible depends on the risk from changing the directory. Another option is to move the directory out of the way, leaving behind a symlink. `find` does not follow symlinks unless you force it to do so. You can then move the directory back. This second pattern minimizes the time when there's a risk. – Jonathan Leffler Mar 25 '15 at 21:18

2 Answers2

1

find does that quite well for you with the -path and -prune options. For example to find all directories except one named /opt/web/DONOTCHGRP under the /opt/web directory:

find /opt/web -path /opt/web/DONOTCHGRP -prune -exec <script> '{}' \;

Then simply include your chmod g+w "$1"; chgrp mygroup "$1"; in a short script and make it executable (the < and > above are just for emphasis and not part of the actual command). find will call the script for all files and directories, except /opt/web/DONOTCHGRP and the files/dirs below it.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • 'Twould be nice to use the `+` option in place of `\;` but the script would need to use `"$@"` in place of `"$1"`. – Jonathan Leffler Mar 25 '15 at 21:15
  • Yes, agreed, but I was hoping to avoid the subtleties of that in the explanation along with the `-exec` and `-exedir` differences. – David C. Rankin Mar 25 '15 at 21:20
  • This did the exact opposite of what I wanted - it only set the group and changed the mode for the DONOTCHGRP directory. After a little research, I added the -o (logical OR) to the command: find ${TARGET_PATH} -path ${SKIPPATH} -prune -o -exec ${SCRIPT} '{}' \; and it worked. Thank you very much for the help!! – David H. Smith Mar 26 '15 at 12:06
  • If you are not using an absolute path for `/opt/web`, then adjust the prune accordingly. e.g. `find . -path ./opt/web/DONOTCHGRP -prune -exec – David C. Rankin Mar 26 '15 at 15:24
1
find /opt/web -not -group mygroup | 
grep -v -e IGNORE1 -e IGNORE2 -e IGNORE3 ... |  
xargs -I {} sh -c '{ chmod g+w {}; chgrp mygroup {};}'
Antxon
  • 1,855
  • 15
  • 21