Assuming there is no sub-directory under sub_x
directories as when if sub_x
directory was contain only one regular file but one or more subdirectories or other type of files or symlinks, then they will be removed as you are requested to rename that one file with its parent directory; so, be noted.
# !/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
dry-run output:
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
remove echo
s in the command to perform real action of the mv
and rm
commands. result:
root_directory
├── sub_a.html
├── sub_b.html
└── sub_c
├── index.css
└── index.html
find ... -type d -execdir bash -c '...' _ {} \;
find
only -d
irectories and execute inline-script bash -c '...'
within (usage of the -execdir
action) each directory it found.
for file in "$1"/*; do
[[ -f "$file" ]] && (( $((++filesCount)) > 1 )) && exit 1;
done;
travers all the files from the directory path returned by the $1
and checks if that's a -f
ile then increment a variable and at the same time verifying if its value exceed more than 1 (meaning that directory have at least 2 files), if so then exit from the inline-script and find
command will read next directory to continue process on; exit
is used to shorten the process time and do not continue counting files in that directory as it doesn't meet our condition for that directory (directory containing one file only).
((filesCount==1)) && mv -v "$file" "${file%/*}.${file##*.}" && rm -r "$1"
checks if filesCount is equal 1 then rename the file and remove the directory; ${file%/*}
and ${file##*.}
used is known Shell Parameter-Expansion.
find . -type d -empty -delete
; I can use rename