bash +特定のパスの下のフォルダが数字で終わるかどうかを確認する方法

bash +特定のパスの下のフォルダが数字で終わるかどうかを確認する方法

/var/kafkaフォルダの下のすべてのフォルダが数字で終わっていることを確認したいと思います。それ以外の場合、エラーが発生して終了します。

ls -ltr  /var/kafka
drwxr-xr-x 399 kafka kafka 28672 Nov  9 13:10 data6
drwxr-xr-x 392 kafka kafka 28672 Nov  9 13:10 data5
drwxr-xr-x 391 kafka kafka 28672 Nov  9 13:10 data1
drwxr-xr-x 405 kafka kafka 28672 Nov  9 13:10 data2
drwxr-xr-x 386 kafka kafka 28672 Nov  9 13:10 data4
drwxr-xr-x 389 kafka kafka 28672 Nov  9 13:10 data8
drwxr-xr-x 406 kafka kafka 28672 Nov  9 13:10 data7
drwxr-xr-x 397 kafka kafka 28672 Nov  9 13:10 data3

だから私は次のような単純なコードを作成しました(bashスクリプトになければなりません)。

for i in `  ls -ltr  /var/kafka | awk '{print $NF}' `; do  [[ ! $i  = *?[0-9] ]] && echo "ERROR folder/s not ended with number" && exit 1 ; done

/var/kafkaしかし、上記のサンプルコードは長すぎて、下のフォルダが数字で終わるかどうかを簡単に確認するために、他のエレガントな短いコマンドを探したいと思います。

awk/sed/またはPerlライナーにも使用できます。

答え1

そしてzsh

files=( /var/kafka/*[^0-9](ND) )
if (( $#files )); then
  print -rlu2 -- "There are files whose name doesn't end in an ASCII digit:" ' - '$^files
  exit 1
fi

bash同じ

shopt -s nullglob dotglob
shopt -u failglob
files=( /var/kafka/*[^0123456789] )
if (( ${#files[@]} )); then
  echo>&2 "There are files whose name doesn't end in an ASCII digit:"
  printf>&2 ' - %s\n' "${files[@]}"
  exit 1
fi

tこれらのファイルのデフォルト名のみを表示するには、/ ail(foo代わりに/var/kafka/foo)とをに置き換えます$^files$^files:t"${files[@]}""${files[@]##*/}"

厳密に言えば、*[^0-9](または*[^0123456789]bashで)数字で終わらないファイル名の場合は、^*[0-9]zsh(必要)set -o extendedglobまたは!(*[0-9])bash(必要shopt -s extglob)で数字以外の文字で終わるファイル名と一致します。名前は空白にできません。これは同じでなければなりません。

エラーメッセージにファイルを一覧表示する必要がない場合は、zshで次のように短縮できます。

if () (( $# )) /var/kafka/*[^0-9](NDY1); then
  print -ru2 "There are files whose name doesn't end in an ASCII digit"
  exit 1
fi

最初の一致項目の表示を中止し、Y1一致項目のリストを$#1つ以上の引数(ゼロ以外)が渡された場合はtrueを返す匿名関数に渡します。

特定の種類のファイルのみを考慮する必要がある場合目次それでもzshの/glob修飾子に追加します。

dirs=( /var/kafka/*[^0-9](ND/) )
if (( $#dirs )); then
  print -rlu2 -- "There are directories whose name doesn't end in an ASCII digit:" ' - '$^dirs
  exit 1
fi

bashにはglob修飾子はありませんが、find名前は数字で終わらないディレクトリタイプファイルを報告できます。

bash4.4以降を使用し、以下findをサポートしてください-print0

readarray -td '' dirs < <(
  cd /var/kafka &&
    LC_ALL=C find . ! -name . -prune -type d ! -name '*[0-9]' -print0
)
if (( ${#dirs[@]} )); then
  echo>&2 "There are dirs whose name doesn't end in an ASCII digit:"
  printf>&2 ' - %s\n' "${dirs[@]}"
  exit 1
fi

以前のバージョンのbashでは、常にループ内の配列を埋めることができます。

dirs=()
while IFS= read -rd '' dir; do
  dirs=("${dirs[@]}" "$dir")
done < <(
  cd /var/kafka &&
    LC_ALL=C find . ! -name . -prune -type d ! -name '*[0-9]' -print0
)

他のロケールでしばしば0と9の間を並べ替える他の何千もの文字の代わりに0123456789でのみこれらのLC_ALL=C一致を使用し、ゼロ以上の文字からゼロ以上のバイトと一致する項目も作成します。[0-9]**[0-9]

一部のロケールでは、0123456789に加えて一部の文字を含む文字エンコーディングが使用され、エンコードは0123456789と同じバイト値で終わります。たとえば、中国で使用されるGB18030文字セットでは、次のようになります。

$ LC_ALL=zh_CN.gb18030 luit
$ locale charmap
GB18030
$ printf %s '¾' | LC_ALL=C od -tx1 -tc
0000000  81  30  86  36
        201   0 206   6
0000004

この文字は明確な理由で0から9の間でソートされ、GB18030エンコーディングはバイト0x36で終わるため、通常はエンコード方法に関係なく¾一致します。これはASCII数値文字のエンコーディングでもあります。[0-9]6

したがって、Cロケールでは、GB18030エンコーディングで構成されたファイルパスは/var/kafka/¾¾¾ASCII番号で終わるものとして扱われ、報告されません。それが必要かどうかは別の問題です。

答え2

使用find:

LC_ALL=C find /var/kafka -mindepth 1 -maxdepth 1 -type d -regex '.*[^0-9]$' | grep '^' \
&& echo "Error in folder name"

合理的な戻りコードを取得するために「虐待」しています。grepより良い方法を知っている人がいれば教えてください。

答え3

別の変形:

[ -z "$(LC_ALL=C find /var/kafka -mindepth 1 -maxdepth 1 -type d \( -name '*[0-9]' -o -print -quit \))" ]

$?すべてのディレクトリ名が数字で終わる場合はtrue(0)を返します。

関連情報