
拡張子を変更せずに複数レベルのサブディレクトリにあるすべてのファイルの名前を再帰的に変更するには?
以下は(スペースを節約するために)私が持っているものの単純化されたバージョンです。議論のために、すべてのファイルのタイトルは同じですが、元の拡張子は維持したいと思います。ディレクトリごとに1つ以上のファイルが存在しないため、複製できません。
単純化のために、これらをすべて呼び出し、foo
その後に現在の拡張子を付けます。
したがって、明確にすると、、、、
Asset\ 1.pdf
はAsset\ 1.png
、、、などになります。Asset\ [email protected]
Asset\ 1.svg
foo.pdf
foo.png
foo.png
foo.svg
私は通常、for
次のようにパラメータ拡張と反復を使用します。
for f in */*; do mv "$f" "${f%/*}/foo.${f##*.}"; done
しかし、再帰的ではありません。だから私はfind
..-exec
または同様のものを使用することを好みます。
~/Desktop/Project/Graphics/
├── Huge
│ ├── PDF
│ │ └── Asset\ 1.pdf
│ ├── PNG
│ │ ├── 1x
│ │ │ └── Asset\ 1.png
│ │ └── 4x
│ │ └── Asset\ [email protected]
│ └── SVG
│ └── Asset\ 1.svg
├── Large
│ ├── PDF
│ │ └── ProjectAsset\ 2.pdf
│ ├── PNG
│ │ ├── 1x
│ │ │ └── ProjectAsset\ 2.png
│ │ └── 4x
│ │ └── ProjectAsset\ [email protected]
│ └── SVG
│ └── ProjectAsset\ 2.svg
├── Medium
│ ├── PDF
│ │ └── ProjectAsset\ 3.pdf
│ ├── PNG
│ │ ├── 1x
│ │ │ └── ProjectAsset\ 3.png
│ │ └── 4x
│ │ └── ProjectAsset\ [email protected]
│ └── SVG
│ └── ProjectAsset\ 3.svg
├── Small
│ ├── PDF
│ │ └── ProjectAsset\ 4.pdf
│ ├── PNG
│ │ ├── 1x
│ │ │ └── ProjectAsset\ 4.png
│ │ └── 4x
│ │ └── ProjectAsset\ [email protected]
│ └── SVG
│ └── ProjectAsset\ 4.svg
└── Tiny
├── PDF
│ └── Asset\ 5.pdf
├── PNG
│ ├── 1x
│ │ └── Asset\ 5.png
│ └── 4x
│ └── Asset\ [email protected]
└── SVG
└── Asset\ 5.svg
30 directories, 20 files
答え1
これは次のようによく似ていますfind...-exec
。引数拡張を使用できるようにシェルを呼び出し、新しいファイル名を構成できるようにディレクトリを抽出PARENT
してから、移動/名前変更を実行します。EXTENSION
PARENT/NAME.EXTENSION
find target_dir -name '?*.*' -type f -exec sh -c '
ret=0
for file do
head=${file%/*}
mv -- "$file" "$head/NAME.${file##*.}" || ret=$?
done
exit "$ret"' sh {} +
上記をDry Runするには、echo
前に挿入してください。mv
隠しファイルも処理します。
アクセス権がある場合は、以下をzsh
実行できます。
autoload zmv
zmv -n '(**/)(*.*)' '${1}NAME.${2:e}'
-n
結果が満足であれば削除してください。
(#qD)
隠しファイルはデフォルトではスキップされますが、それを処理するにはglob修飾子を使用できます。
autoload zmv
zmv -n '(**/)(?*.*)(#qD)' '${1}NAME.${2:e}'
答え2
Bashを使用している場合は、すべてのディレクトリを繰り返すことをお勧めします。
$ shopt -s globstar
$ for f in ./Desktop/**/*; do [[ -f $f ]] &&
mv -n "$f" "${f%/*}/foo.${f##*.}"; done
既存のファイル(存在する場合)を上書きしないように-n
追加されました。mv
これはfind(in)を介して行うこともできます。一つシェル呼び出し(ファイルごとに1つのシェルを呼び出すよりも高速):
$ find ./Desktop -type f -exec sh -c '
for f; do echo mv -n "$f" "${f%/*}/foo.${f##*.}"; done' findsh {} \+
echo
このコマンドが要件を満たしている場合は、削除してください。
答え3
単純すぎるかもしれませんが、ディレクトリ階層の最大深さ(ここでは3)を知っているとしたらどうでしょうか。
for f in */* */*/* */*/*/*; do ... ; done
エラーチェックを追加しますか?
答え4
find ~/Desktop/Project/Graphics/ -type f -exec sh -c 'f={}; mv $f ${f%/*}/foo.${f##*.}' \;
sh
デフォルトのシェル呼び出しを表します。 bash、zshなどに変更できます。