特定の文字数を含むすべてのファイル名を取得する

特定の文字数を含むすべてのファイル名を取得する

すべてのファイル名を正確に16文字(数字と小文字)に変更したいと思います。[0-9a-z]{16}次のコードスニペットで[0-9a-z]\{16\}プレースホルダを試しましたが、うまくregXいきません。

for file in <regX>
do
  mv "$file" "${file}.txt"
done

答え1

シェルワイルドカードモード正規表現ではありません。。似ているように見えるかもしれませんが、ある点では非常に異なる動作をします。

正規表現は、[0-9a-z]{16}上記の文字範囲を含む16文字の文字列と一致します(埋め込まれた文字列は長くなる可能性があります)。

同等のシェルワイルドカードパターンは次のようになります。

*[0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z]*

このためです

  1. ワイルドカードモードは、「最初のN回の繰り返し」修飾子をサポートしません。
  2. デフォルトでは、ワイルドカードパターンは開始と終了に固定されています。だから*パターンの始めと終わりに挿入します。 A は*任意の数のすべての文字と一致します。一致が必要な場合は、以下を削除してください。正確に16文字。

Perlを使用して16ビット文字列を作成できます[0-9a-z]

$ pattern="$( perl -e 'print "[0-9a-z]" x 16' )"

を使用すると、オプションでbash現在のディレクトリのすべての名前を繰り返し、名前が正規表現と一致するかどうかをテストできます。

for name in *; do
    if [[ -f "$name" ]] && [[ "$name" =~ ^[0-9a-z]{16}$ ]]; then
        echo mv "$name" "$name.txt"
    fi
done

echoそれが正しいことをしていることがわかったら、それを取り除きます。

長い名前が一致しないようにパターンを固定しました。また、-f私たちが得た名前が実際に一般的なファイルの名前であることを確認するためにテストしました。

答え2

そして外部グローバル変数

shopt -s extglob
for file in +([0-9a-z])
do
    [[ ${#file} == 16 ]] && echo mv "$file" "${file}.txt"
done
  • +([0-9a-z])1 つ以上の[0-9a-z]文字を表します。
  • ${#file}ファイル名の長さを指定します
  • echoテストの実行に使用し、すべてがうまくいったら削除します。

答え3

renamePerl-rename(Debianベースのシステムまたは他のシステムから呼び出されます)がある場合は、perl-rename次のことができます。

perl-rename -n 's/^[0-9a-z]{16}$/$&.txt/' *

要件を満たしている場合は、それらを削除して-n実際にファイル名を変更してください。構文perl-renameはperlコマンドです。ここでは、代替演算子(s/from/to/)を使用してfromを置き換えますto。この場合、from正規表現は「一致する項目」を表すto特殊変数$&と拡張子です.txt


Shell globを使用してこれを行うには(使用@クサラナンダまたは@サンディップメソッドは完了のためです):

for f in [0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z]; do
    mv -- "$f" "$f".txt
done

GNUの使用find:

find . -regextype posix-extended -regex '.*/[0-9a-z]{16}' -exec mv {} {}".txt" \;

答え4

L16=$(csh -c 'repeat 16 echo -n "?"')
find . -name "$L16" ! -name '*[!0-9a-z]*' -exec sh -c '
   mv "$1" "$1.txt"
' {} {} \;

関連情報