我有一个在文件夹中运行的 shell 函数(在我的例子中,它查找 *.eps` 文件并将它们转换为没有空白边框的 pdf)。让我们通过以下函数对此进行抽象:
function do_here() {
echo $(pwd)
}
我寻找一种智能方法来遍历给定根路径的目录和路径ROOT_PATH
并do_here
在每个树叶上进行操作。可能会有象征性的叶子,但目前这个要求似乎是一个优点。
理由似乎是
ROOT_PATH
使用 alias遍历目录to_path
;- 跑步
cd $to_path
; - 跑步
do_here
; - 转到步骤 2。
我不知道如何获取步骤 1 中的目录路径列表。
答案1
Bash 还支持**
递归通配符,前提shopt -s globstar
是已设置。如果你用 .glob 为后缀,你只能得到目录/
。添加dotglob
这样您就不会错过名称以点开头的目录。
所以,例如
#!/bin/bash
shopt -s globstar
shopt -s dotglob
do_here() {
echo "working in $(pwd)...";
}
# cd ROOT_PATH
for d in **/; do (
cd "$d"
do_here
)
done
请注意,shell 之间的工作方式存在一些差异**
,即在目录树内的符号链接方面。如果树包含到另一个目录的链接,至少某些版本的 Bash 会跟随它,可能会超出树的范围。 (我不确定你所说的“象征性叶子”是什么意思,所以我不知道这是否是一个问题。)
答案2
要获取所有目录,就像获取目录中的所有文件一样,您可以使用通配;然后,您将使用循环for
来迭代结果,并启动子 shell ( ( commands in subshell )
) 或pushd
/popd
堆栈上的目录。例如:
#!/usr/bin/zsh
for directory in **/*(ND/) ; do
print -r -u2 Working on ${directory}
( # do in subshell, so that `cd` doesn't affect
# the next iteration
cd -- "${directory}" && \
do_here # && : only if `cd` succeeded, do `do_here`
) || {
print -r -- "${directory} failed" >&2 | \
logger -p user.err
}
done
让我们把它拆开
for directory in **/*(ND/) ; do
# ^ ^---+---^ ^ ^ ^^^
# | | | | ||\ *(/) extended glob: match directories
# | | | | |\- *(N) extended glob: null glob, i.e., don't fail if
# | | | | | nothing matches
# | | | | \-- *(D) extended glob: include directories starting with
# | | | | ".", i.e., normally hidden dirs
# | | | \---- * glob operator
# | | \------- **/ apply the following globbing recursively
# | |
# | \---------------- "loop variable": `directory` gets set to each result,
# | consecutively
# |
# \---------------------- for {variable name} in {list-generating expression} :
# for loop