如何仅根据名称跳过 for 循环中的子目录?

如何仅根据名称跳过 for 循环中的子目录?

我有一个目录,按以下方式组织成子目录:

a1
b1
c1
c2
c3
d1

我正在尝试执行仅在给定字母的最新子目录上执行的循环,即它将循环遍历a1, b1, c3, 和d1,但忽略c1c2。到目前为止,我的努力主要围绕直接尝试比较子目录名称的数值,但这并没有取得很好的效果。我是 bash 新手,所以如果这是我缺少的一个简单修复,我深表歉意。

答案1

这似乎实现了你的目标

#!/bin/bash
for DIR in {a..z}
do
 GOOD=$(find ${DIR}[0-9] -type d -print -prune 2>/dev/null | tail -1)
 if [[ "$GOOD" ]]; then
  echo $GOOD
 fi
done

用法示例:

$ mkdir a1 b1 c1 c2 c3 d1
$ ./a.sh
a1
b1
c3
d1
$

答案2

我有一个有点复杂的小管道来完成你的工作:

#!/bin/bash
find . -maxdepth 1 -type d |
sed -e '/\.$/d' -e '/\.\.$/d' -e 's/\.\/\(.\)\(.\)/\1   \2/' |
sort -k1.1 -k2.1n |
awk 'BEGIN {last=""}
        {
                if (last == "") {
                        last = $1; number = $2
                } else if ($1 != last) {
                        printf "%s%s\n", last, number;
                        last = $1; number = $2
                } else {
                        number = $2
                }
        }
        END { printf "%s%s\n", last, number }
'

您可能必须更改参数才能find得到您想要的结果。

答案3

对系列中的最后一个进行操作的一种方法是循环遍历所有元素,记住前一项。如果您检测到新系列即将开始,请对记住的前一项进行操作。未经测试的代码。我假设您只对第一个字符不是点且最后一个字符是数字的目录感兴趣。

act_on () {
}
previous_prefix=0
previous_name=
for x in *[0-9]/; do
  x=${x%/}
  digits=${x##*[!0-9]}
  prefix=${x%"$digits"}
  if [ "$prefix" != "$previous_prefix" ] && [ "$previous_prefix" != "0" ]; then
    # New prefix, so act on the previous element
    act_on "$previous_name"
  fi
  previous_prefix=$prefix
  previous_name=$x
done
act_on "$previous_name"

请注意,它foo9是在 之后排序的foo10。在 zsh 中,use*[0-9](/on)使用数字排序,其中9之前已排序10。如果您不使用 zsh,则需要采用不同的方法。一种方法是仅对系列的第一项进行操作,而不是对您找到的项进行操作,而是使用其前缀并确定数字系列的最后一个元素。

act_on () {
}
previous_prefix=0
previous_name=
for x in *[0-9]/; do
  x=${x%/}
  digits=${x##*[!0-9]}
  prefix=${x%"$digits"}
  if [ "$prefix" != "$previous_prefix" ]; then
    suffixes=
    for y in "$prefix"*; do
      suffixes="$suffixes
${y#"$prefix"}"
    done
    last_suffix=$(echo "$suffixes" | sort -n | tail -n 1)
    act_on "$prefix$last_suffix"
  fi
  previous_prefix=$prefix
  previous_name=$x
done

答案4

如果您的目录名称像您显示的那样简单(至少,如果不包含空格或其他奇怪的内容),您可以这样做:

for d in $(ls | sort -r | rev | uniq -s1 | rev); do echo "$d"; done

将 更改echo "$4d"为您的循环应该执行的操作。但是,如果您的目录名称与您显示的不完全一样,这将失败,因为它容易受到所有陷阱解析 ls.它的工作原理是首先列出目录,以相反的顺序对它们进行排序,反转它们(因此a1变成1a),仅保留唯一的行但忽略第一个字符(uniq -s1),然后重新反转它们以恢复原始名称。

相关内容