ファイルセットの名前を変更する Bash 正規表現

ファイルセットの名前を変更する Bash 正規表現

コマンド (正規表現を使用)を使用して、一連のファイルの名前を変更する必要がありますrename。 何度か試してみましたが、期待どおりの結果が得られるような表現が見つかりません。

次のようなファイルパターンがあります:

プレフィックス_誰かの名前_その他.txt

すべてのファイルは「」文字列で始まりprefix_、「」で終わり_other.txt誰かの名前部分は、アンダースコアで区切られた複数の(英数字の)単語で構成できます。つまり、次のようになります。

prefix_one_name_other.txt
prefix_this_is_my_name_1_this1_other.txt

ファイル名を次のように変更する必要があります:

他の名前日付時刻
other_this-is-my-name-1-this1_日付時刻

言い換えると:

  • 「 」を削除する必要がありますprefix(アンダースコアはそのままにします)
  • " other" トークンはファイル名の先頭に移動します
  • 誰かの名前、アンダースコア(_)をダッシュ​​(-)に変換します
  • ファイル名の末尾のアンダースコア(誰かの名前)は残らなければならない
  • 拡張機能を削除する必要があり.txtます。日付時刻

私が試したこと:

rename 's/fw_([a-z]+)_(\d)_(\w+\d)_(\w+)\.txt/$4_$1-$2-$3_'$datahora'/' *.txt

$datahoraもっている日付時刻値(テスト済み)。これは期待通りに動作します

prefix_name_1_gnt1_other.txt

しかし、

prefix_other_name_2_gnt2_other.txt

どこで間違えたのでしょうか? 他にどうすればそれを達成できるでしょうか?

今のところ、私が持っているすべてのファイル名に機能する正規表現を見つけることができないので、私は頭を悩ませています。文字列の最初の要素は常に一部でありprefix、最後の要素はother.txt文字列の一部であることはわかっています。したがって、文字列を配列に分割し、新しい名前を構築するために必要な項目を取得することは可能です。実際、そのようなことです。

datahora="20140718-080000"
arrfiles=( *.txt )
for curfile in ${arrfiles[*]}
do
    arrparts=( ${curfile//_/ } )
    numitems=${#arrparts[*]}
    newname=""
    for (( c=1; c<numitems-1; c++ ))
    do
        newname+="${arrparts[c]}-"
    done
    newname=${newname%-}
    arrparts[numitems-1]=${arrparts[numitems-1]/.txt/}
    newname="${arrparts[numitems-1]}_${newname}_$datahora"
    echo "$curfile pasa a $newname"
    mv ${curfile} ${newname}
done

この方法を実行した後、@peterph の提案をもう一度試し、最終的にいくつかの名前変更正規表現の組み合わせを実行しました。次のような感じでした:

rename 's/_/-/g' *.txt
rename 's/^fw-(.*)-([^-]*)(\.txt)/$2.$1$3/' *.txt
rename 's/(\w+)\.(.*)(\.txt)/$1_$2_'$datahora'/' *.txt

何が最善のアプローチかはわかりません。私の意見では、正規表現バリアントの方がエレガントに見えますが、作業を実行するには 3 回の名前変更操作 (ディスクへの 3 回のアクセス) が必要ですが、バリアントではarrayディスクへの書き込みは 1 回だけです。

これら 2 つの解決策についてどう思いますか?

再度、感謝します。

答え1

rename複数の置換コマンドを受け入れることができない限りそしてファイル名のルート ( some_name) に複数のアンダースコアが含まれる場合、これを 2 つの手順で行う必要があります。a) アンダースコアをダッシュ​​に置き換え、b) ファイル名内のチャンクを (再) 移動します。

探している正規表現の例は次のとおりです。

rename 's/_/-/g' *.txt
rename 's/^prefix-(.*)-([^-]*).txt$/$2_$1_'$DATETIME'/' *txt

最初のものはアンダースコアをダッシュ​​に変換し、後者はルートとサフィックスを交換し、DATETIME環境変数の内容を名前に追加します。もちろん、プレフィックスと拡張子は省略します。

部分[^-]*は、ダッシュを含まない任意の文字列に一致します。サフィックスが常に同じ場合は、プレフィックスの場合と同様に、そのままそこに配置できます (逆の場合も同様です。プレフィックスが変化する可能性がある場合は、^[^-]*-ファイル名の先頭と (つまり) 最初のダッシュの間にあるダッシュを含まない任意の文字列として一致させるために を使用します)。

複数のコマンドをサポートしている場合はrename、それらを連結するだけです。

rename 's/_/-/g;s/^prefix-(.*)-([^-]*).txt$/$2_$1_'$DATETIME'/' *txt

関連情報