我正在尝试递归地更改 WordPress 安装中的文件权限,影响 public_html 文档根文件夹下的所有内容(不包括某些文件夹)。
我已将 extglob 设置为shopt -s extglob
当我运行以下命令时,它无法排除我希望排除的文件夹
ls -R -alh ./public_html/!(*uploads*) | grep uploads
上面列出了上传文件夹中的大量文件——它不应该列出任何文件。
当然上面的命令只是一个测试;我将chmod
在实际脚本中使用。
我尝试了许多不同的组合,但都失败了;例如,以下内容:
ls -R -alh ./public_html/!(wp-content/uploads*)
ls: 无法访问 ./public_html/!(wp-content/uploads*): 没有这样的文件或目录
这是我第一次尝试在 shell 命令中使用排除,我可能会犯一个简单的错误。
有什么想法我做错了吗?
请注意:问题的目的是为了更好地理解 extglob 而不是寻找替代方案。我可以编写替代方案,但由于我之前从未使用过 extglob,所以在理解语法时遇到了困难。
答案1
首先,extglob 控制ls
在其命令行上看到的内容。确实如此不是控制ls
它在命令行上看到的内容的作用。这很重要,因为告诉探索的-R
选项ls
ls
递归地它在命令行上看到的任何目录。因此,即使*uploads*
没有在命令行上明确给出目录,ls
在探索其父目录时也会找到它们。
其次,如你所知,不解析 ls。的输出ls
不适用于管道或脚本。试图以这种方式使用它最终会导致不快乐。
第三,要获取所需的文件,请尝试:
find ./public_html ! -path '*uploads*'
解释:
告诉
./public_html
find 开始在./public_html
目录中查找。就其本身而言,该选项
-path '*uploads*'
匹配包含模式的任何路径*uploads*
。 (与 find 的选项-path
类似,但包含目录名称。)但是前面的 表示否定。因此,该选项排除任何匹配的路径。-name
path
!
! -path '*uploads*'
*uploads*
ls
要在仍然使用 的功能的同时获得样式输出find
,请考虑:
find ./public_html ! -path '*uploads*' -exec ls -dalh {} +
答案2
John1024 为您明显的问题添加了一个很好的解决方案,但根据评论,您想更好地理解 extglob。我怀疑核心误解之一可能是 extglobs 将以递归方式工作——这种说法./public_html/!(*uploads*)
会排除名为 的东西./public_html/wp-content/uploads/
。 glob(文件名扩展)一次只能在单个目录级别上工作。埋在 bash 手册中,在文件名扩展是:
匹配文件名时,斜杠字符必须始终显式匹配。
因此,正如 John1024 所说,该ls
命令没有任何形式的(扩展的)参数./public_html/*uploads*
,但它可能有一个参数,例如./public_html/wp-content
(与排除的模式不匹配),然后它被-R
告知递归列表。
为了*uploads*
在命令行中使用 extglobs 排除目录,您必须构建一个具有与子目录一样多的排除项的命令:
ls -dalh ./public_html/!(*uploads*) \
./public_html/!(*uploads*)/!(*uploads*) \
./public_html/!(*uploads*)/!(*uploads*)/!(*uploads*)
# ... etc ...
...还要小心不要使用 ls 的-R
标志。同样的-R
风险也适用于 chmod 命令。这里的一个潜在风险是,如果任何子目录有“太多”文件,您将面临风险填充参数列表为了ls
。这种方法很脆弱,因为它不会捕获比您编写的模式数量更深的新创建的目录,并且ls
如果您曾经有过,它会破坏(会抱怨缺少目录)更少子目录的数量比给定模式的数量多,这是为什么的长解释寻找是适合这项工作的工具。