![特定の文字数を持つファイル名をすべて取得する](https://rvso.com/image/109243/%E7%89%B9%E5%AE%9A%E3%81%AE%E6%96%87%E5%AD%97%E6%95%B0%E3%82%92%E6%8C%81%E3%81%A4%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%90%8D%E3%82%92%E3%81%99%E3%81%B9%E3%81%A6%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B.png)
すべてのファイル名を 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]*
それの訳は
- グロブ パターンは、「前の N 回を繰り返す」という修飾子をサポートしていません。
- グロブパターンは、デフォルトでは先頭と末尾に固定されます。そのため、
*
パターンの先頭と末尾に挿入しました。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
rename
perl-rename ( Debian ベースのシステムでは呼び出され、他のシステムでは呼び出されます) がある場合はperl-rename
、次のように実行できます。
perl-rename -n 's/^[0-9a-z]{16}$/$&.txt/' *
これで目的の動作が実現したら、 を削除して、-n
実際にファイル名を変更するようにします。 の構文はperl コマンドです。ここでは、を に置き換えるperl-rename
置換演算子 ( ) を使用しています。この場合の は正規表現で、 は「一致したもの」を意味する特殊変数に拡張子 を加えたものです。s/from/to/
from
to
from
to
$&
.txt
これをシェルグロブ(使用)で実行するには@Kusalananda のまたは@サンディープのアプローチ、これは完了のためだけです) :
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"
' {} {} \;