I am trying to recursively change file permissions in a wordpress installation affecting everything below the public_html document root folder, excluding certain folders.
I have set extglob on with shopt -s extglob
When I run the following command it fails to exclude the folder I want it to exclude
ls -R -alh ./public_html/!(*uploads*) | grep uploads
The above lists numerous files in the uploads folder — it should not list any.
Of course the command above is only a test; I'll be using chmod
in the actual script.
I have tried numerous different combinations and all have failed; for example, the following:
ls -R -alh ./public_html/!(wp-content/uploads*)
ls: cannot access ./public_html/!(wp-content/uploads*): No such file or directory
This is my first attempt to use exclusions with shell commands and I might be making a simple mistake.
Any ideas what I am doing wrong?
Please note: the purpose of the question is to better understand extglob rather than find alternatives. I can script alternatives but as I have never used extglob before I am having trouble understanding the syntax.
Best Answer
First, the extglob controls what
ls
sees on its command line. It does not control whatls
does with what it sees on the command line. This is important because the-R
option tols
tellsls
to explore recursively any directories it sees on the command line. So, even if the*uploads*
directories are not given explicitly on the command line,ls
will find them when it explores their parent directories.Second, as you know, don't parse ls. The output of
ls
is not meant for use in pipelines or scripts. Trying to use it that way eventually leads to unhappiness.Third, to get the files that you want, try:
To explain:
The
./public_html
tells find to start looking in the./public_html
directory.By itself, the option
-path '*uploads*'
matches on any path that contains the pattern*uploads*
. (-path
is similar to find's-name
option butpath
includes the directory names.) The preceding!
, however, indicates negation. So, the option! -path '*uploads*'
excludes any path matching*uploads*
.To get
ls
style output while still using the features offind
, consider: