回答:
移植可能な方法(POSIX準拠のシステムで動作します):
find /the/path -depth -name "*.abc" -exec sh -c 'mv "$1" "${1%.abc}.edefg"' _ {} \;
bash4では、globstarを使用して再帰的なグロブ(**)を取得できます。
shopt -s globstar
for file in /the/path/**/*.abc; do
mv "$file" "${file%.abc}.edefg"
done
rename
Ubuntu の(perl)コマンドは、perl正規表現構文を使用してファイルの名前を変更できます。この構文は、globstarまたはと組み合わせることができますfind
:
# Using globstar
shopt -s globstar
files=(/the/path/**/*.abc)
# Best to process the files in chunks to avoid exceeding the maximum argument
# length. 100 at a time is probably good enough.
# See http://mywiki.wooledge.org/BashFAQ/095
for ((i = 0; i < ${#files[@]}; i += 100)); do
rename 's/\.abc$/.edefg/' "${files[@]:i:100}"
done
# Using find:
find /the/path -depth -name "*.abc" -exec rename 's/\.abc$/.edefg/' {} +
${1%.abc}...
sh -c
、最初の引数が$ 0に割り当てられ、残りの引数が位置パラメータに割り当てられているため必要です。したがって、_
は仮引数であり、 '{}'はに対する最初の位置引数sh -c
です。
これは、すべてのファイルが同じフォルダーにある場合に必要なタスクを実行します
rename 's/.abc$/.edefg/' *.abc
ファイルの名前を再帰的に変更するには、次を使用します。
find /path/to/root/folder -type f -name '*.abc' -print0 | xargs -0 rename 's/.abc$/.edefg/'
rename 's/.abc$/.edefg/' /path/to/root/folder/**/*.abc
、最新バージョンのBashで。
s
先頭に、そして他のどのような選択肢私はそこで使用することができます。ありがとう!
再帰的な名前変更の問題の1つは、ファイルの検索に使用する方法が何であれrename
、ファイル名だけでなく、パス全体をに渡すことです。そのため、ネストされたフォルダーで複雑な名前の変更を行うのが難しくなります。
この問題を解決するためにfind
の-execdir
アクションを使用します。の-execdir
代わりに使用する場合-exec
、指定されたコマンドは、一致したファイルを含むサブディレクトリから実行されます。したがって、パス全体をに渡すのではなく、rename
のみを渡し./filename
ます。これにより、正規表現を簡単に記述できます。
find /the/path -type f \
-name '*.abc' \
-execdir rename 's/\.\/(.+)\.abc$/version1_$1.abc/' '{}' \;
詳細に:
-type f
ディレクトリではなくファイルのみを探すことを意味します-name '*.abc'
は、.abcで終わるファイル名のみに一致することを意味します'{}'
-execdir
見つかったパスを挿入する場所をマークするプレースホルダーです。スペースとシェル文字を含むファイル名を処理できるようにするには、単一引用符が必要です。-type
およびの後ろのバックスラッシュ-name
は、bashの行継続文字です。この例を使用して読みやすくしましたが、コマンドをすべて1行に入力する場合は必要ありません。-execdir
行の最後にバックスラッシュが必要です。セミコロンをエスケープするためにあり、によって実行されたコマンドを終了し-execdir
ます。楽しい!正規表現の説明:
s/
正規表現の開始\.\/
-execdirが渡す先頭の./と一致します。\を使用して。および/メタキャラクター(注:この部分は、バージョンによって異なりますfind
。ユーザー@apolloからのコメントを参照してください)(.+)
ファイル名と一致します。括弧は、後で使用するために一致をキャプチャします\.abc
ドットをエスケープし、abcと一致します$
文字列の最後に一致を固定します
/
正規表現の「一致」部分の終わりと「置換」部分の始まりをマークします
version1_
このテキストをすべてのファイル名に追加します
$1
かっこでキャプチャしたため、既存のファイル名を参照します。「一致」部分で複数の括弧のセットを使用する場合、ここで$ 2、$ 3などを使用してそれらを参照できます。.abc
新しいファイル名は.abcで終わります。ここで「置換」セクションでドットメタキャラクターをエスケープする必要はありません。/
正規表現の終わり前
tree --charset=ascii
|-- a_file.abc
|-- Another.abc
|-- Not_this.def
`-- dir1
`-- nested_file.abc
後
tree --charset=ascii
|-- version1_a_file.abc
|-- version1_Another.abc
|-- Not_this.def
`-- dir1
`-- version1_nested_file.abc
ヒント:rename
の-nオプションは便利です。ドライランを実行し、変更する名前を表示しますが、変更は行いません。
--execdir
、先頭にパスしなかった./
ため\.\/
、正規表現の一部を省略できます。私はOSXないUbuntuの上だからかもしれないことがある
# Rename all *.txt to *.text
for f in *.txt; do
mv -- "$f" "${f%.txt}.text"
done
また、解析しない理由のエントリも参照してくださいls
。
編集:basenameを使用する必要がある場合、構文は次のようになります。
for f in *.txt; do
mv -- "$f" "$(basename "$f" .txt).text"
done
https://unix.stackexchange.com/questions/19654/changing-extension-to-multiple-files
これが私がしたことであり、私が望んでいた通りに機能しました。mv
コマンドを使用しました。複数の.3gp
ファイルがあり、それらをすべて名前を変更したかった.mp4
以下に短いワンライナーを示します。
for i in *.3gp; do mv -- "$i" "ren-$i.mp4"; done
単に現在のディレクトリをスキャンして、すべての.3gpファイルを取得し、(mvを使用して)名前を ren-name_of_file.mp4
file.3gp
れfile.3gp.mp4
ます。
.3gp
または.mp4
、ここでは説明のためだけでした。
basename "$i" .mp4
「ren- $ i.mp4」の代わりに以前の拡張子を削除するために使用します。
同じ名前のパッケージ からmmvコマンドを使用します。
mmv ';*.abc' '#1#2.edefg'
は;
0個以上*/
に一致#1
し、置換で一致します。に*
対応し#2
ます。非再帰バージョンは
mmv '*.abc' '#1.edefg'
ファイルとディレクトリの名前を変更します find -execdir | rename
単に接尾辞を付けるのではなく、ファイルとディレクトリの両方の名前を変更する場合、これは良いパターンです。
PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
find . -depth -execdir rename 's/findme/replaceme/' '{}' \;
awesome -execdir
オプションはcd
、rename
コマンドを実行する前に、ディレクトリとは異なり-exec
ます。
-depth
親ディレクトリの欠落に伴う潜在的な問題を防ぐために、最初に子、次に親で名前変更が行われることを確認してください。
-execdir
名前変更はベース名以外の入力パスではうまく機能しないため、たとえば次のように失敗します。
rename 's/findme/replaceme/g' acc/acc
PATH
ので、ハッキングが必要です-execdir
:1つの非常に迷惑な欠点がありfind
、非常に独断で、で何かをすることを拒否し-execdir
、あなたの内の相対パスがあればPATH
、環境変数を、例えば./node_modules/.bin
、で失敗します:
find:相対パス './node_modules/.bin'はPATH環境変数に含まれています。これは、findの-execdirアクションと組み合わせた場合、安全ではありません。そのエントリを$ PATHから削除してください
参照:「-execdir」アクションの使用が、PATHにあるディレクトリに対して安全でないのはなぜですか?
-execdir
はPOSIXの GNU find 拡張機能です。rename
Perlベースで、rename
パッケージに由来します。Ubuntu 18.10。でテスト済み。
先読み回避策の名前を変更する
入力パスがから来ていないfind
場合、または相対的なパスの煩わしさが十分にある場合、Perlの先読みを使用して、次のようにディレクトリの名前を安全に変更できます。
git ls-files | sort -r | xargs rename 's/findme(?!.*\/)\/?$/replaceme/g' '{}'
私はのために便利なアナログを発見していない-execdir
とxargs
:https://superuser.com/questions/893890/xargs-change-working-directory-to-file-path-before-executing/915686
sort -r
長いパスが同じプレフィックスを持つ短いものの後に来るので、ファイルは、それぞれのディレクトリの後に来ることを保証するために必要とされます。