想定されるディレクトリ構成
testdir/
├── animals
│ ├── cat
│ ├── dog
│ └── horce
├── colors
│ ├── black
│ ├── blue
│ ├── brown
│ ├── gold
│ ├── green
│ ├── orange
│ ├── pink
│ ├── red
│ ├── silver
│ ├── white
│ └── yallow
└── vegetables
├── carot
├── potato
└── tomato
step by step
ディレクトリごとのファイル数を取得する
-
ls -1
でファイルリストを出力しwc
で行数をカウント-
-U
はソートしないオプション。なくてもいい
-
- ディレクトリごとに
wc
を実行するために、xargs
でls
とwc
をまとめて実行
$ cd testdir
$ find . -type d | xargs -I{} sh -c "ls -U1 {} | wc -l"
3
3
11
3
最大数を取得する
-
sort -g
で数値順に並べ替えてtail -n1
で最大を取得
$ cd testdir
$ find . -type d | xargs -I{} sh -c "ls -U1 {} | wc -l" | sort -n | tail -n1
11
桁数を取得する
- bashなら「桁数を計算して変数に格納」より「変数に格納して長さを取得」のほうが楽
$ cd testdir
$ max="$(find . -type d | xargs -I{} sh -c "ls -U1 {} | wc -l" | sort -gb | tail -n1 | sed 's/ //g')"
$ echo "${#max}"
2
桁数を揃えて連番を出力
-
printf
で整形 - bashの
(())
で加算-
10#
で十進数扱いにしないと八進数扱いにされエラーが出る
-
- ループする必要がなければ
seq -w 1 10
とかでいい
$ cd testdir
$ max="$(find . -type d | xargs -I{} sh -c "ls -U1 {} | wc -l" | sort -gb | tail -n1 | sed 's/ //g')"
$ while [ $num -le 10 ]; do
> num="$(printf "%0${#max}d" "$((10#$num+1))")"
> echo "$num"
> done
01
02
03
04
05
06
07
08
09
10
11
リネーム
- ディレクトリ内の全ファイルに対してループ処理するには
for 変数 in *
でよい-
for 変数 in "$dir"/*
でもいいけど、リネームがめんどかった
-
コード
というわけで、完成したスクリプト。カレントディレクトリのサブディレクトリを検索し、ファイル名の先頭に連番を付ける。
while read dir; do
num=0
cd "$dir"
for file in *; do
num="$(printf "%0${#max}d" "$((10#$num+1))")"
mv "$file" "$num-$file"
done
cd -
done < <(find . -type d -mindepth 1)
結果
- ファイル数が100でも100000でも同じスクリプトでイケる
- ディレクトリ階層が深くてもイケるが、ディレクトリをリネームしないように
for
あたりをいじらないと
testdir
├── animals
│ ├── 01-cat
│ ├── 02-dog
│ └── 03-horce
├── colors
│ ├── 01-black
│ ├── 02-blue
│ ├── 03-brown
│ ├── 04-gold
│ ├── 05-green
│ ├── 06-orange
│ ├── 07-pink
│ ├── 08-red
│ ├── 09-silver
│ ├── 10-white
│ └── 11-yallow
└── vegetables
├── 01-carot
├── 02-potato
└── 03-tomato