私は次のディレクトリ構造を持っています:
root_directory
--sub_a
----index.html
--sub_b
----index.html
--sub_c
----index.css
----index.html
これで、ファイルを親ディレクトリに移動し、親フォルダの名前にちなんで名前を変更したいのですが、そのファイルが子ディレクトリにある唯一のファイルである場合にのみ可能です。これにより、次のようにディレクトリが効果的に平坦化されます。
root_directory
--sub_a.html
--sub_b.html
--sub_c
----index.css
----index.html
これを達成するための賢明な方法はありますか?できますが、find . -name 'index.html'
ディレクトリにそのファイル以外のファイルが含まれているかどうかをさらに確認する方法がわかりません。これらのファイルのリストがあれば上に移動できますが、(mv path/index.html ..
)何らかの方法でフォルダ名を再利用して名前を変更する方が賢明かもしれません。
ベストアンサー1
sub_x
通常のファイルのみが含まれているが、1つ以上のサブディレクトリや他の種類のファイルまたはシンボリックリンクを含むディレクトリなど、ディレクトリの下にサブディレクトリがないと仮定すると、ファイル名を親ディレクトリにsub_x
変更するように求められます。削除されましたのでご注意ください。
# !/bin/bash
find /path/to/root_directory/ -type d -execdir bash -c '
for file in "$1"/*; do
[[ -f "$file" ]] && (( $((++filesCount)) > 1 )) && exit 1;
done;
((filesCount==1)) && echo mv -v "$file" "${file%/*}.${file##*.}" && echo rm -r "$1"
' _ {} \; 2>/dev/null
テスト実行出力:
mv -v ./sub_b/index.html ./sub_b.html
rm -r ./sub_b
mv -v ./sub_a/index.html ./sub_a.html
rm -r ./sub_a
echo
実行するコマンドmv
とrm
コマンドの実際の操作からsを削除します。結果:
root_directory
├── sub_a.html
├── sub_b.html
└── sub_c
├── index.css
└── index.html
find ... -type d -execdir bash -c '...' _ {} \;
find
ディレクトリのみ-d
とインラインスクリプトの実行bash -c '...'
以内に(このタスクの使い方-execdir
)見つけたすべてのディレクトリについて。
for file in "$1"/*; do
[[ -f "$file" ]] && (( $((++filesCount)) > 1 )) && exit 1;
done;
返されたディレクトリパス内のすべてのファイルを繰り返し、ファイルであることを$1
確認してから-f
、変数を増やし、その値が1を超えていることを確認し(ディレクトリに少なくとも2つのファイルがあることを意味します)、そうであればインラインスクリプトを終了します。コマンドの処理を続行するには、find
次のディレクトリを読みます。exit
処理時間を短縮するために使用され、そのディレクトリ内のファイルは、そのディレクトリ(ファイルが1つしか含まれていないディレクトリ)の基準を満たしていないため、まだ計算されません。
((filesCount==1)) && mv -v "$file" "${file%/*}.${file##*.}" && rm -r "$1"
filesCountが1であることを確認してからファイル名を変更してディレクトリを削除すると、使用方法がわかります${file%/*}
。${file##*.}
シェルパラメータ拡張。