サブフォルダごとにファイルを名前で並べ替え、拡張子に関係なく連続したパディング番号に名前を変更します。

サブフォルダごとにファイルを名前で並べ替え、拡張子に関係なく連続したパディング番号に名前を変更します。

次のディレクトリ構造があります。

.
├── event-a
│   ├── album-a
│   │   ├── a.jpg
│   │   └── x.png
│   └── album-b
│       ├── a.jpg
│       ├── x.png
│       └── y.gif
└── event-b
    ├── album-x
    │   ├── a.jpg
    │   └── x.png
    └── album-y
        ├── a.jpg
        ├── x.png
        └── y.gif

2番目のレベルの各サブフォルダ(album-foo例では名前付け)について、ファイルを名前で並べ替え、拡張子に関係なく連続パディング番号に名前を変更したいと思います。これらのフォルダにはJPG、PNG、またはGIFイメージを含めることができ、すべてのファイル拡張子を保持する必要があります。

したがって、この場合は次のようなものを得たいと思います。

.
├── event-a
│   ├── album-a
│   │   ├── 01.jpg
│   │   └── 02.png
│   └── album-b
│       ├── 01.jpg
│       ├── 02.png
│       └── 03.gif
└── event-b
    ├── album-x
    │   ├── 01.jpg
    │   └── 02.png
    └── album-y
        ├── 01.jpg
        ├── 02.png
        └── 03.gif

rename実用的な事項物事が簡単になったら使用してください。

主な問題は、各ファイルがどれだけ得られるべきかを把握することです。入れ子になったforループを使用して繰り返し、サブフォルダを作成し、event-x各内部ループについて直接数値を追跡する必要がありますかalbum-x、それとも私が見逃した賢い解決策はありますか?

答え1

for dir in */*; do           # loop over the directories
    (                        # run in a subshell ...
        cd "$dir"            # ... so we don't have to cd back
        files=(*)            # store the filenames in a zero-indexed array

        for index in "${!files[@]}"; do
            file=${files[$index]}
            ext=${file##*.}
            newname=$(printf "%02d.%s" $((index+1)) "$ext")
            mv "$file" "$newname"
        done
    )
done

拡張子のないファイルがあるとしましょう。この場合、前の数字を除いて名前は同じです(例:my_file=> 05.my_file)。

ディレクトリを含む非表示にされていないすべてのディレクトリエントリの名前が変更されます。

答え2

ここには2つの質問があります。

  1. ディレクトリに再帰します。
  2. 各個々のディレクトリで番号付けシステムを再起動します。

これにより、どちらの場合もスムーズに処理されますが、他の拡張も含めることにした場合は、IMAGE_TYPES変数を変更する必要があります。

#!/bin/bash

shopt -s extglob
shopt -s nocaseglob

IMAGE_TYPES='jpg|png|gif'
IFS=$'\n' dirlist=(`find "$PWD" -type d`)

for dir in "${dirlist[@]}"; do
    cd "$dir"
    ls *.+($IMAGE_TYPES) > /dev/null 2>&1 || continue

    counter=0
    for file in *.+($IMAGE_TYPES); do
        printf -v newname "%.3d.%s" $((counter += 1)) "${file##*.}"
        mv --verbose "$file" "$newname"
    done
done

答え3

私は同じツリーを作成し、モバイルビルドを実行しました。これが私が思いついたものです:

n=0 IFS=.; set -f ./[e]vent*/*/*
for f do [ -n "${f##./\[*}" ] || break
    [ "$d" = "${f%/*}" ] || i=0 d=${f%/*}
    mv=': mv "${'$((n=$n+1))'}" "${'$n'%%/*}/'
    printf "$mv%.2d%.0s.%s\"\n" $((i=$i+1)) ${f##*/}
done | sh -sx -- "$@"

最後のパイプがない場合は、|次を印刷します。

mv "${1}" "${1%/*}/01.jpg"
mv "${2}" "${2%/*}/02.png"
mv "${3}" "${3%/*}/01.jpg"
mv "${4}" "${4%/*}/02.png"
mv "${5}" "${5%/*}/03.gif"
mv "${6}" "${6%/*}/01.jpg"
mv "${7}" "${7%/*}/02.png"
mv "${8}" "${8%/*}/01.jpg"
mv "${9}" "${9%/*}/02.png"
mv "${10}" "${10%/*}/03.gif"

わかりましたが、あまりそうではありませんが、ここで重要なのは、奇妙なファイル名や他のものについて心配する必要はないということです。この出力の目的のターゲットは、forループを共有して出力を生成したシェルです。位置の配列。私のコマンドには次のコマンドがあります。次のデバッグ出力を提供するように構成されています。

+ : mv ./event-a/album-a/a.jpg ./event-a/album-a/01.jpg
+ : mv ./event-a/album-a/x.png ./event-a/album-a/02.png
+ : mv ./event-a/album-b/a.jpg ./event-a/album-b/01.jpg
+ : mv ./event-a/album-b/x.png ./event-a/album-b/02.png
+ : mv ./event-a/album-b/y.gif ./event-a/album-b/03.gif
+ : mv ./event-b/album-x/a.jpg ./event-b/album-x/01.jpg
+ : mv ./event-b/album-x/x.png ./event-b/album-x/02.png
+ : mv ./event-b/album-y/a.jpg ./event-b/album-y/01.jpg
+ : mv ./event-b/album-y/x.png ./event-b/album-y/02.png
+ : mv ./event-b/album-y/y.gif ./event-b/album-y/03.gif

:これがフォーマット文字列の最初の文字の場合の外観ですprintf。それを削除してコマンドを実行すると、次のようになります。

ls ./event*/*/

./event-a/album-a/:
01.jpg  02.png

./event-a/album-b/:
01.jpg  02.png  03.gif

./event-b/album-x/:
01.jpg  02.png

./event-b/album-y/:
01.jpg  02.png  03.gif

これはあなたの要件を満たすようです。結果に勝つことはできないと思います。

答え4

ファイル名がわかっている場合は、次を実行してその番号を取得できます。

ls -1 <your_dir> | grep <file_name> -B 1000 | wc -l

関連情報