当您说 bash 时,您的真正意思是在 bash 中还是只是使用常用命令行工具编写脚本?
脚本工具组合
find . -type f -exec chmod u+x {} \;
这意味着对当前目录中的每个文件都使其可执行。 \; 将 ; 传递给 find 命令,该命令将其解释为“在每个找到的路径上单独调用 exec 字符串”。您可以将\; 替换为\+,它告诉find 首先收集所有路径并将其替换为{}。通常\+ 可能更有效,但您必须小心命令行长度,因为存在限制。然后你可以做的就是将它与 xargs 结合起来:
find . -type f -print0 | xargs -0 -P $(nproc) -I{} chmod u+x {}
它的作用是告诉 find 使用空字符作为终止符而不是换行符。这可确保您正确处理每个条目,即使它具有任意空格或随机 UTF 字符(\0 不是路径的有效部分)。 xargs 的 -0 选项告诉它在读取参数而不是 newliens 时使用 \0 作为分隔符。 -P 选项表示并行运行命令 N 次,在这种情况下 N 是打印处理器数量的 nproc 命令的输出。 -I 是替换字符串,其余的是要处理的命令字符串。
find 和 xargs 的手册页非常适合探索。
在 Bash 中原生
如果您正在寻找完全在 Bash 中且没有外部工具的解决方案,那么它会稍微复杂一些,并且会涉及一些更高级的 Bash 特定语言结构,您可以在其中自行实现。要遍历目录的内容,您可以执行for path in <dir>; do 之类的操作。然后,您将使用内置的测试 [[ -d "$path" ]] 来确定它是否是目录,[[ -f "$path" ]] 是否是文件等(man test 有很多解释,但请注意这是独立的 test 可执行文件,它有细微的差别以及来自功能更丰富、更安全的 bash 版本 [[ ]] 的缺陷。
使用 bash 数组:https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_10_02.html
Bash测试介绍:https://www.tldp.org/LDP/abs/html/testconstructs.html
那个测试介绍没有提到像正则表达式这样的东西,它们将成为该语法的一部分。 Bash 还具有强大的选项来操作变量的内容:https://www.tldp.org/LDP/abs/html/parameter-substitution.html
但在实践中,即使是适度复杂的任何东西(无论是在 bash 中还是通过组合工具),都可能在 Python 中得到更好的维护和更易于阅读(作为在 Bash 方面拥有大量丰富经验的人而言)。
find_files() {
if [[ ! -x "$1" ]]; then
echo "$1 isn't a directory" >&2
return 1
fi
local dirs=("$1")
while [[ "${#dirs[@]}" -gt 0 ]]; do
local dir="${dirs[0]}"
dirs=("${dirs[@]:1}") # pop the element from above
# whitespace in filenames iterated will be a problem. Look to the IFS
# variable to handle those more gracefully.
for p in "${dir}"/*; do
if [[ -d "$p" ]]; then
dirs+=("$p")
elif [[ -f "$p" ]]; then
echo "$p"
fi
done
done
}
for f in $(find_files .); do
chmod u+x "$f"
done
正如您所见,这比仅使用 find/xargs 二进制文件更复杂、更棘手且更慢。你永远不会想在现实中写出这样的东西。您甚至可以在将find_files 转换为process 的地方变得更有趣,方法是让它接受一个命令,然后在您通过eval 进行迭代(而不是回显路径)时对其进行评估。 eval 非常棘手,可能是一个安全漏洞。