就地操作并输出结果

就地操作并输出结果

我有一个在文件夹中运行的 shell 函数(在我的例子中,它查找 *.eps` 文件并将它们转换为没有空白边框的 pdf)。让我们通过以下函数对此进行抽象:

function do_here() {
    echo $(pwd)
}

我寻找一种智能方法来遍历给定根路径的目录和路径ROOT_PATHdo_here在每个树叶上进行操作。可能会有象征性的叶子,但目前这个要求似乎是一个优点。

理由似乎是

  1. ROOT_PATH使用 alias遍历目录to_path
  2. 跑步cd $to_path;
  3. 跑步do_here;
  4. 转到步骤 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

相关内容