bashスクリプトを使用してファイル名を一括変更するには?

bashスクリプトを使用してファイル名を一括変更するには?

ディレクトリには次の形式のファイルが複数あるので、すべてのファイルの名前を次のように変更したいと思います。

~から

27_07_2017file1vc001vpxd-1605.log
27_07_2017case2vc001vpxd-9169.log
27_07_2017server3vc001vpxd-4640.log
27_07_2017file24vc001vpxd-9170.log
27_07_2017files5vc001vpxd-4641.log

到着

file1vc001vpxd-1605_27_07_2017_1.log
case2vc001vpxd-9169_27_07_2017_1.log
server3vc001vpxd-4640_27_07_2017_1.log
file24vc001vpxd-9170_27_07_2017_1.log
files5vc001vp-4641_27_07_2017_1.log

ファイルの種類をdatefilename.log次から変更する必要があります。filename.date_1.log

rename私のLinuxサーバーでは機能しないので、コマンドを提案しないでください。

ありがとう

答え1

これはbashスクリプトです(一般的な状況に合わせて修正OPの修正された質問に基づいています):

for file in ./*.log; do 
    echo mv "$file" "${file:12:$((${#file}-16))}_${file:2:10}_1.log";
done

上記は${file:X:Y}bashサブストリング拡張構文${variable:offset:length}で、次のようになります。長さ文字数オフセットそれvariable(または引数)でmvコマンドを使用して名前を変更します。echo結果が希望の結果であると確信したら、削除してください。

上記の結果は次のとおりです。

mv ./27_07_2017case5.log case5_27_07_2017_1.log
mv ./27_07_2017file1vc001vpxd-1605.log file1vc001vpxd-1605_27_07_2017_1.log
mv ./27_07_2017file2vc001vpxd-9169.log file2vc001vpxd-9169_27_07_2017_1.log
mv ./27_07_2017file3vc001vpxd-4640.log file3vc001vpxd-4640_27_07_2017_1.log
mv ./27_07_2017file4vc001vpxd-9170.log file4vc001vpxd-9170_27_07_2017_1.log
mv ./27_07_2017file5.log file5_27_07_2017_1.log
mv ./27_07_2017file5vc001vpxd-4641.log file5vc001vpxd-4641_27_07_2017_1.log
mv ./27_07_2017number-blahblahblah5.log number-blahblahblah5_27_07_2017_1.log
mv ./27_07_2017number-blahblahblah5AAABBC.log number-blahblahblah5AAABBC_27_07_2017_1.log
mv ./27_07_2017number5.log number5_27_07_2017_1.log

答え2

あなたの場合には2つのコンポーネントがあります。 ファイル名そして日付

再帰検索を使用してすべてのログファイルを一覧表示する

find "$(pwd)" -type f -iname "*.log" > loglist

サブディレクトリに繰り返さずにすべてのログファイルを一覧表示する

find "$(pwd)" -maxdepth 0 -type f -iname "*.log" > loglist

これで、whileループを使用してファイルを目的の形式に移動できます。

while read f;
do
    # filename only and not complete path
    fname_only=$(basename "$f");
    
    # directory name only without filename
    dirname_only=$(dirname "$f");
    
    # use cut command to extract first 10 characters as date from filename
    date_only=$(echo "$fname_only" | cut -c 1-10);

    # use cut command to extract 11th character onward as new filename with extension
    fname_extract=$(echo "$fname_only" | cut -c 11-);

    # filename with complete path without extension 
    fname_no_extns="${fname_extract%.*}"

    # Now, move files to their desired format recursively
    mv "$f" "${dirname_only}/${fname_no_extns}.${date_only}_1.log"

done < loglist

答え3

私はファイル名について考えられるすべてのケースを知らないので、あなたのニーズに合わせて調整できる一般的なアプローチを紹介します。

ループを使用してファイルを繰り返すforか、find -exec必要に応じて繰り返すことができます。私は主にファイル名を複数の部分に切り取り、さまざまな方法で組み合わせる方法を知りたいと思います。

同様のツールに名前を付けsedて正規表現を生成して、必要な部分を識別できます。

newname=`echo "$oldname"|sed -E 's/([0-9-]{10})(.*).log/\2_\1_1.log/'`

これらの部品を周囲に配置することで、()交換文字列で等と参照できます\1\2調整が必要な場合はページを読んで、調整が行われない場合はこちらからお問い合わせくださいmansed

別の可能性は、POSIX変数拡張を使用することです。

あなたは知っているかもしれません

${oldname#*201?}

ファイル名から日付プレフィックスを削除します(?すべての文字と一致する可能性があるため、十分な場合は2010年から2019年まで機能します。そうでない場合は調整してください。)

次のように組み合わせることもできます。

${oldname%${oldname#*201?}}

上記から抽出した部分は削除されるため、日付のみが表示されます。これにより、ファイル名の一部を分離して別の順序で貼り付けることができます。

答え4

必須 zsh + zmv 答え:

autoload -Uz zmv
zmv -n '(<1-31>_<1-12>-<1900-2999>)(*).log' '$2.${1}_1.log'

満足すれば削除します-n(テスト実行用)。

関連情報