[^A-Za-z0-9._-]
私は特定のファイル形式(この場合)を除くすべての文字を見つけて下線に置き換えるスクリプトを書いています。現在のパスで再帰的に実行したいです。私はUbuntuを使用しています。.avi
_
フォルダ名を作成するときにフォルダ名を制御できるため、フォルダ名を変更したり変更したりする必要はありません。次のリンクを参照して、現在私が持っているものは次のとおりです。
find . -depth -exec rename 's!([^/]*\Z)/[^A-Za-z0-9._-]/_/g' *.avi {} +
私は明らかに何かを見逃しています。助けてください。 :)
答え1
コードが機能しない理由
ワイルドカードパターンは*.avi
以前に実行されたシェルによって拡張されるため、その効果は現在のディレクトリにファイルがあるかどうかによって異なります。バラよりfind
find
*.avi
ファイルが一番上にある場合、検索は繰り返されません。もっと説明したい。サブディレクトリから拡張するには、*.avi
3つの異なる操作を実行する必要があります。元のシェルが拡張されないようにパターンを引用し、ワイルドカード拡張を実行するために各サブディレクトリで追加のシェルを実行するように調整し、ファイル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ベースのバリエーションrename
とfind
サポートされている実装の使用-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 ... {} \;
zmv
mv
mv
zmodload zsh/files
- 使用
-execdir
、find
実行コマンドディレクトリにこれらのファイルを含み、ディレクトリへの相対パスをコマンドに渡します。いくつかのfind
実装(GNU実装)は./
ファイルにプレフィックスを追加しますが、一部はそうではありません。 dorename
accept オプションの一部の変形後ろにつまり、名前が.perlで始まるファイルがある場合、-
問題が発生する可能性があります。 - ファイル名に一連のバイトが含まれていても、そうでない場合は、ロケールで有効な文字を形成するために
LC_ALL=C
forを使用する必要があります。これは継承され、ほとんどのバリアントではASCIIでのみ機能します。ただし、これはマルチバイト文字をその文字と同じバイト数に置き換えることを意味します。たとえば、UTF-8はマルチバイト文字と文字でデコードできないすべてのバイトをそれぞれ1文字に変換するため、名前をに変更することをお勧めします。-name
rename
_
stéphane
st__phane
st_phane
zsh
_
- とは異なり、
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
。