名前だけでforループでサブディレクトリをスキップするには?

名前だけでforループでサブディレクトリをスキップするには?

次のようにサブディレクトリとして構成されたディレクトリがあります。

a1
b1
c1
c2
c3
d1

指定された文字の最新のサブディレクトリでのみ実行されるループを実行しようとしています。つまりa1、、、、b1およびc3を繰り返しますが、合計はd1無視されます。これまでの努力は、サブディレクトリ名の数値を直接比較することにのみ集中していましたが、うまくいきませんでした。私は初めてbashに触れたので、これが私が見逃した簡単な修正であれば謝罪します。c1c2

答え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

シリーズの最後の要素で作業する1つの方法は、前の項目を覚えながらすべての要素を繰り返すことです。新しいシリーズがまもなく開始されることを検出したら、以前に記憶された項目に対処してください。テストされていないコード。私は、最初の文字がドットではなく、最後の文字が数字であるディレクトリにのみ興味があると仮定します。

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)数値ソートを使用します。 zshを使用しない場合は、別のアプローチを取る必要があります。 1つのアプローチは、系列の最初の項目に対してのみ演算を実行し、見つかった項目に対して演算を実行する代わりに、プレフィックスを使用して数値系列の最後の要素を決定することです。910

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、逆順に復元して元の名前を復元するように機能します。1auniq -s1

関連情報