我有一个 bash 脚本,其功能类似于以下内容:
for src in $(find -H "$DOTFILES_ROOT" -maxdepth 2 -name '*.sym' -not -path '*.git*')
do
dst="$HOME/$(basename "${src%.*}")"
link_file "$src" "$dst"
done
我已经在我的脚本上运行了 shellcheck 并且它返回了
For loops over find output are fragile. Use find -exec or a while read loop.
我读过并理解了,这对我来说很有意义,例如
find -H "$(pwd)" -maxdepth 2 -name '*.sym' -not -path '*.git*' -exec echo {} \;
但我不确定如何使其与 for 循环中的变量一起使用
答案1
循环中的变量for
是src
和dst
。 src
是由 赋予循环的文件的路径名find
并由dst
计算得出src
。
您的循环可以转换为find -exec
如下命令:
find -H "$DOTFILES_ROOT" -maxdepth 2 -type d -name '.git' -prune -o \
-type f -name '*.sym' -exec sh -c '
link_file "$1" "$HOME/$( basename "${1%.*}" )"' sh {} ';'
我假设您-not -path '*.git*'
不打算查看.git
目录。这与-type d -name '.git' -prune
上面的命令相同,但-prune
我们find
甚至停止进入这些目录。
一旦我们清除了.git
目录,我们就开始寻找.sym
文件。当找到一个时,循环中的命令就会被执行。该命令通过sh -c
(以便能够通过参数替换和 执行一些奇特的事情)执行basename
,并且找到的文件的路径名在内部可用$1
。
人们甚至可以将您的循环(几乎)按照您所写的那样合并:
find -H "$DOTFILES_ROOT" -maxdepth 2 -type d -name '.git' -prune -o \
-type f -name '*.sym' -exec sh -c '
for src do
dst="$HOME/$( basename "${src%.*}" )"
link_file "$src" "$dst"
done' sh {} +
在这种情况下,sh -c
脚本给出的不是单个路径名,而是多个路径名(由于+
末尾的-exec
),因此我们循环遍历这些路径名并执行操作。
有关的: