拡張子を変更せずにすべてのファイルの名前を再帰的に変更しますか?

拡張子を変更せずにすべてのファイルの名前を再帰的に変更しますか?

拡張子を変更せずに複数レベルのサブディレクトリにあるすべてのファイルの名前を再帰的に変更するには?

以下は(スペースを節約するために)私が持っているものの単純化されたバージョンです。議論のために、すべてのファイルのタイトルは同じですが、元の拡張子は維持したいと思います。ディレクトリごとに1つ以上のファイルが存在しないため、複製できません。

単純化のために、これらをすべて呼び出し、fooその後に現在の拡張子を付けます。

したがって、明確にすると、、、、
Asset\ 1.pdfAsset\ 1.png、、、などになります。Asset\ [email protected]Asset\ 1.svg

foo.pdffoo.pngfoo.pngfoo.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してから、移動/名前変更を実行します。EXTENSIONPARENT/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などに変更できます。

関連情報