名前変更を使用してファイル名(ディレクトリを除く)の無効な文字を繰り返し変更するスクリプト

名前変更を使用してファイル名(ディレクトリを除く)の無効な文字を繰り返し変更するスクリプト

[^A-Za-z0-9._-]私は特定のファイル形式(この場合)を除くすべての文字を見つけて下線に置き換えるスクリプトを書いています。現在のパスで再帰的に実行したいです。私はUbuntuを使用しています。.avi_

フォルダ名を作成するときにフォルダ名を制御できるため、フォルダ名を変更したり変更したりする必要はありません。次のリンクを参照して、現在私が持っているものは次のとおりです。

SEリファレンス

find . -depth -exec rename 's!([^/]*\Z)/[^A-Za-z0-9._-]/_/g' *.avi {} +

私は明らかに何かを見逃しています。助けてください。 :)

答え1

コードが機能しない理由

ワイルドカードパターンは*.avi以前に実行されたシェルによって拡張されるため、その効果は現在のディレクトリにファイルがあるかどうかによって異なります。バラよりfindfind*.aviファイルが一番上にある場合、検索は繰り返されません。もっと説明したい。サブディレクトリから拡張するには、*.avi3つの異なる操作を実行する必要があります。元のシェルが拡張されないようにパターンを引用し、ワイルドカード拡張を実行するために各サブディレクトリで追加のシェルを実行するように調整し、ファイルfindタイプの代わりにコマンドを使用します。検索ディレクトリ。

また、コードはrename最終的に{} +rename

また、Perlコードに構文エラーがあります。

zshを使用した作業ソリューション

autoload -Uz zmv # best in ~/.zshrc

zmv -n '(**/)(*.avi)(#qD^/)' '$1${2//[^a-zA-Z0-9._-]/_}'

^/はい除外を選択してください目次。次.へ交換定期的なファイルのみ。-nある試運転。満足のいくものを削除してください。

find実際のソリューションrename

Perlベースのバリエーションrenamefindサポートされている実装の使用-execdir

LC_ALL=C find . -depth -name '*[!a-zA-Z0-9._-]*.avi' ! -type d -execdir \
  rename 's/[^a-zA-Z0-9._-]/_/g' {} +

ただし、このアプローチにはいくつかの注意事項があります。

  • 走る少なくともrename名前を変更するファイルを含むディレクトリごとに1つのインスタンスがあります(ファイルごとに1つ、一部の実装/バージョンrenameではfind実際に-execdir ... {} +は。 。-execdir ... {} \;zmvmvmvzmodload zsh/files
  • 使用-execdirfind実行コマンドディレクトリにこれらのファイルを含み、ディレクトリへの相対パスをコマンドに渡します。いくつかのfind実装(GNU実装)は./ファイルにプレフィックスを追加しますが、一部はそうではありません。 do renameaccept オプションの一部の変形後ろにつまり、名前が.perlで始まるファイルがある場合、-問題が発生する可能性があります。
  • ファイル名に一連のバイトが含まれていても、そうでない場合は、ロケールで有効な文字を形成するためにLC_ALL=Cforを使用する必要があります。これは継承され、ほとんどのバリアントではASCIIでのみ機能します。ただし、これはマルチバイト文字をその文字と同じバイト数に置き換えることを意味します。たとえば、UTF-8はマルチバイト文字と文字でデコードできないすべてのバイトをそれぞれ1文字に変換するため、名前をに変更することをお勧めします。-namerename_stéphanest__phanest_phanezsh_
  • とは異なり、zsh名前の変更を開始する前にzmv完全なチェックは行われません(たとえば、両方のファイルは同じ名前a+b.aviで終わりません)。ただし、既存のファイルを上書きしないでください。[email protected]rename

答え2

私たちが言うと

rename 's/[^A-Za-z0-9.-]/_/g' -- *.avi

現在のディレクトリのファイル名サフィックスを含むすべてのファイルの名前を正しく変更し、現在のディレクトリ.avi(現在のディレクトリを含む)の下のすべてのディレクトリに適用できます。

find . -type d -exec sh -c '
    for dirpath do
        ( cd "$dirpath" && rename "s/[^A-Za-z0-9.-]/_/g" -- *.avi )
    done' sh {} +

見つかったディレクトリ配置の場合は、見つかったディレクトリに変更してコマンドを実行する短いインラインスクリプトを実行しますrename

関連情報