如何在 shell 中进行子目录操作?

如何在 shell 中进行子目录操作?

例如,对 n 个已排序的子目录运行命令,其中 n 是输入。或者如何在一系列子目录上运行 for 循环,在其中可以将该范围作为输入?就像下面这样,除了我如何在这里定义范围?

for d in ["sd1"-"sd2"] do ( cd "$d" && do stuff ) done

答案1

如果您有支持大括号扩展的 shell,请使用大括号扩展:

for d in sd{1..2}; do
    ( cd "$d" && dostuff )
done

使用zsh,ksh93yash -o braceexpand(但不是bash),你可以这样做

n=4
for d in sd{1..$n}; do
    ( cd "$d" && dostuff )
done

相关问题:我可以在没有“eval”的情况下在 {} 扩展中使用变量吗?

对此的一个变体是

for (( i=1; i<=n; ++i )); do
  str="sd$i"
  ( cd ... )
done

for这是 和其他 shell支持的C 风格循环bash(尽管仍然是 POSIX 标准的扩展)。

答案2

使用zsh,您可以执行以下操作:

for d (sd<1-10>(Nn-/)) (cd $d && dostuff)
  • <1-10>是一个全局运算符,匹配 1 到 10 之间的十进制整数。它将匹配1, 001... 您可以使其<->匹配任何正十进制整数。
  • (Nn-/)是一个全局限定符。
    • N如果没有匹配则不会失败
    • n按数字对元素进行排序(因此sd10在 后面sd2
    • -/仅包含目录类型的文件(在符号链接解析之后)。

如果您想列出两个日期之间的目录,其中日期编码在目录名称中(如sd2017-08-01):

for d (sd<->-<->-<->(Nne{'
  [[ ! $REPLY < sd2015-06-06 && ! $REPLY > sd2017-08-09 ]]'}-/))
  (cd $d && dostuff)

答案3

其他可能的解决方案是使用seq命令(如果可用)

for i in `seq -f "sd%03.0f" 111 121`
do
( cd "$i" && do stuff )
done

答案4

全局扩展已排序,这意味着您可以执行以下操作:

state=0
for d in *; do
   case $d in "sd1") state=1;; "sd2") break;; esac
   if [ 1 -eq "$state" ]; then
      ( cd "$d" && dostuff )
   fi
done

我在这里假设sd1sd2不是真实的例子,并且该范围不能用微不足道的数值范围来描述。如果可以的话我会用罗密欧·尼诺夫解决方案

大括号扩展非常简洁,但不幸的是,许多 POSIX shell 没有它们,因为它们不是 POSIX 要求。

相关内容