Linuxで特定のパターンに一致するすべてのファイルの名前をまとめて変更するには?

Linuxで特定のパターンに一致するすべてのファイルの名前をまとめて変更するには?

次の内容を含むフォルダがあります。たくさん .mkv手動でファイル名を変更せずにファイル名を変更したいと思います。

パターンは次のとおりです。

...
[XVC]_Control_-_10_-_Doctors_[SCB055Y].mkv
[XVC]_Control_-_11_-_Engineers_[50OPZ00].mkv
...

私は結果が次のようになりたいと思います:

...
Control-10-Doctors.mkv
Control-11-Engineers.mkv
...

私は使用してfind配管を試しましたが、うまく動作しないようです。sedtr

これまでに試したことは次のとおりです。

find . -iname "*.mkv" -exec sed -e 's/\[[^][]*\]//g' {} \;
find . -type f "*mkv" | sed 's/\[[^][]*\]//g' | tr -d '_'
find . "*.mkv" -type f -print0 | xargs -0 sed -i '' -e 's/\[[^][]*\]//g' | tr -d '_'
find . -iname "*.mkv" -exec rename 's/\[[^][]*\]//g' .mkv '{}' \;
find . -iname "*.mkv" -exec rename -n 's/\[[^][]*\]//g' {} ";"

他のものもいくつかありますが、何も動作しないようです。私が気にするのは、次のコマンドが機能することです。

(input)
echo '[XVC]_Control_-_10_-_Doctors_[SCB055Y].mkv' | sed 's/\[[^][]*\]//g' | tr -d '_'`

(output)
Control-10-Doctors.mkv

編集する:

$ file $(which rename)
/usr/bin/rename: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=d7b5a08ee8556c59dbdda26e998e20d4762c2bbc, for GNU/Linux 3.2.0, stripped
rename -n 's/\[.+?\]//g; s/_//g' *mkv
rename: not enough arguments
Try 'rename --help' for more information.

ベストアンサー1

これはperl-renameと一緒に使用されます(ディストリビューションに従って呼び出されますrename):prenameperl-rename

$ rename -n 's/\[.*?\]|_//gs' ./*.mkv
[XVC]_Control_-_10_-_Doctors_[SCB055Y].mkv -> Control-10-Doctors.mkv
[XVC]_Control_-_11_-_Engineers_[50OPZ00].mkv -> Control-11-Engineers.mkv

必要な結果が出たら、-n実際にファイル名を変更せずにもう一度実行してください。

または小さなループを作成してください。

find . -iname "*.mkv" -print0 |
    while IFS= read -rd '' file; do
        newName=$(printf -- '%s\n' "$file" | perl -pe 's/\[.*?\]|_//gs')
        echo mv -- "$file" "$newName"
    done

正しいと思われる場合は、削除してやり直してecho実際にファイル名を変更してください。


いくつかの理由でコマンドは機能しません。

  1. find . -iname "*.mkv" -exec sed -e 's/\[[^][]*\]//g' {} \;

    このコマンドはsedファイル自体に対してコマンドを実行するため、名前ではなくファイルの内容のみが変更されます。使用しないので、これは本当ではありません。-iこれは、変更をstdoutに印刷することを意味します。

  2. find . -type f "*mkv" | sed 's/\[[^][]*\]//g' | tr -d '_'

    ここでfindファイル名は印刷されますが、テキスト(ストリーム)に渡されて入力sedを変更しますが、ファイル名は変更しません。と同じですecho foo | sed 's/f/b/'fooファイルが存在する場合、ファイル名は変更されません。

  3. find . "*.mkv" -type f -print0 | xargs -0 sed -i '' -e 's/\[[^][]*\]//g' | tr -d '_'

    ここでもsedファイルで実行されるため、内容が一致する場合はファイルを実際に変更することを除いて、基本的に上記と同じです。これはバイナリファイルなので、実際に変更する可能性はありませんが、不可能ではありません。

  4. find . -iname "*.mkv" -exec rename 's/\[[^][]*\]//g' .mkv '{}' \;

    これは実際にはファイル名を変更できますが、.mkv文字列をコマンドに最初の引数として渡したので、renameファイル名を変更しようとします.mkv。おそらくそのようなファイルがないので、何もしません。 2番目のパラメータ'{}'は無視されます。これは働きます:

    find . -iname "*.mkv" -exec rename 's/\[[^][]*\]//g' {} \;
    

    ただし、処理しないため、ファイル名を_Control_-_10_-_Doctors_.mkvandに変更します。_Control_-_11_-_Engineers_.mkv_

  5. find . -iname "*.mkv" -exec rename -n 's/\[[^][]*\]//g' {} ";"

    これは役に立ちます!上記の4で述べたように、名前は正しく変更されません。

おすすめ記事