#!/usr/bin/env bash
help_text="
NAME
tidy - Tidies filenames and fixes issues such as permission issues with files in the specified directory.
USAGE
tidy [<folder>]
OPTIONS
-n|--name
Only tidy filenames - do not check permissions etc.
-fn|-nf
Force rename of filenames without prompting. Implies -n.
-h|--help
Show help text.
DESCRIPTION
Tidies filenames and fixes issues such as permission issues with files in the specified directory.
AUTHORS
mjnurse.github.io - 2020
"
help_line="Tidies filenames and fixes issues such as permission issues with files in the specified directory"
web_desc_line="Tidies filenames and fixes issues such as permission issues with files in the specified directory"
force=n
names_only=n
while [[ "$1" != "" ]]; do
case $1 in
-h|--help)
echo "$help_text"
exit
;;
-n|--name)
names_only=y
;;
-fn|-nf)
force=y
names_only=y
;;
-*)
echo "Unknown option: $1"
echo "Try ${0##*/} -h for more information"
exit 1
;;
?*)
cd $1
;;
esac
shift
done
cdef="\e[39m" # default colour
cbla="\e[30m"; cgra="\e[90m"; clgra="\e[37m"; cwhi="\e[97m"
cred="\e[31m"; cgre="\e[32m"; cyel="\e[33m"
cblu="\e[34m"; cmag="\e[35m"; ccya="\e[36m";
clred="\e[91m"; clgre="\e[92m"; clyel="\e[93m"
clblu="\e[94m"; clmag="\e[95m"; clcya="\e[96m"
function cecho {
color=c$1
shift
message="$*"
echo -e "${!color}${message}${cdef}"
}
cecho gre ================================================================================
cecho gre "Filename contains character other than [a-z][0-9]_-."
cecho gre ================================================================================
for f in *; do
if [[ -f "$f" && ! -L "$f" ]]; then
newname=$(echo "$f" | \
sed 's/[^a-zA-Z0-9._-]/_/g;
s/\([A-Z]\)\([A-Z][A-Z]*\)/\1\L\2/g;
s/^\([A-Z]\)/\L\1/;
s/\([A-Z]\)/-\L\1/g;
s/__*/_/g;
s/--*/-/g;
s/_\./\./g;
s/_-/-/g;
s/-_/-/g;
s/__*/_/g;
s/--*/-/g;
')
if [[ "$f" != "$newname" && "$f" != "README.md" ]]; then
echo --------------------------------------------------------------------------------
echo "FILE: $f"
echo "Rename as: $newname"
echo --------------------------------------------------------------------------------
if [[ $force == y ]]; then
opt="r"
else
printf "${clblu}[i]gnore rule, [r]ename, [s]kip, q[uit]. [irSq]?: ${cdef}"
read opt
fi
case $opt in
r|R)
# rename via a temp tile name to avoid the Windows file system saying
# a.txt is same as A.txt etc.
val=$RANDOM
mv "$f" "${newname}.tmp.${val}"
mv "${newname}.tmp.${val}" "$newname"
;;
i|I)
break;;
q|Q)
exit;;
esac
fi
fi
done
if [[ $names_only == y ]]; then
exit
fi
cecho gre ================================================================================
cecho gre Executable but not '#!/usr/bin/env'
cecho gre ================================================================================
for f in $(find . -maxdepth 1 -executable); do
if [[ -f $f && ! -L $f ]]; then
line1="$(head -1 $f)"
if [[ "${line1:0:14}" != "#!/usr/bin/env" ]]; then
echo --------------------------------------------------------------------------------
echo FILE: $f
echo --------------------------------------------------------------------------------
echo First 5 lines:
echo --------------
head -5 $f
echo
printf "${clblu}[i]gnore rule, [r]emove exec, add [b]ash, add [p]ython3, [s]kip, q[uit]. [irbpSq]?: ${cdef}"
read opt
case $opt in
r|R)
chmod a-x $f
;;
b|B)
sed -i '/^#!\/bin\/bash/d' $f
sed -i '1i#!/usr/bin/env bash' $f
;;
p|P)
sed -i '1i#!/usr/bin/env python3' $f
;;
i|I)
break
;;
q|Q)
exit
;;
esac
fi
fi
done
cecho gre ================================================================================
cecho gre '#!/usr/bin/env' but not Executable
cecho gre ================================================================================
for f in $(find . -maxdepth 1 ! -executable); do
if [[ -f $f && ! -L $f ]]; then
line1="$(head -1 $f)"
line1=${line1//[$' \t\r\n']}
if [[ "$line1" == "#!/usr/bin/env" ]]; then
echo --------------------------------------------------------------------------------
echo FILE: $f
echo --------------------------------------------------------------------------------
echo First 5 lines:
echo --------------
head -5 $f
echo
read -p "[i]gnore rule, [d]elete '#!/usr/bin/env', [m]ake exec, [s]kip, q[uit]. [idmSq]?: " opt
case $opt in
d|D)
sed -i '1d' $f;;
m|M)
chmod u+x $f;;
i|I)
break;;
q|Q)
exit;;
esac
fi
fi
done
cecho gre ================================================================================
cecho gre Writable by Other
cecho gre ================================================================================
for f in $(find . -maxdepth 1 -perm -o=w); do
if [[ -f $f && ! -L $f ]]; then
echo --------------------------------------------------------------------------------
ls -al $f
echo
read -p "[i]gnore rule, [r]remove writeable other, [s]kip, q[uit]. [irSq]?: " opt
case $opt in
r|R)
chmod o-w $f;;
i|I)
break;;
q|Q)
exit;;
esac
fi
done
cecho gre ================================================================================
cecho gre Writable by Group
cecho gre ================================================================================
for f in $(find . -maxdepth 1 -perm -g=w); do
if [[ -f $f && ! -L $f ]]; then
echo --------------------------------------------------------------------------------
ls -al $f
echo
read -p "[i]gnore rule, [r]remove writeable group, [s]kip, q[uit]. [irSq]?: " opt
case $opt in
r|R)
chmod g-w $f;;
i|I)
break;;
q|Q)
exit;;
esac
fi
done
cecho gre ================================================================================
cecho gre Executable by Other
cecho gre ================================================================================
for f in $(find . -maxdepth 1 -perm -o=x); do
if [[ -f $f && ! -L $f ]]; then
echo --------------------------------------------------------------------------------
ls -al $f
echo
read -p "[i]gnore rule, [r]remove Exec other, [s]kip, q[uit]. [irSq]?: " opt
case $opt in
r|R)
chmod o-x $f;;
i|I)
break;;
q|Q)
exit;;
esac
fi
done
cecho gre ================================================================================
cecho gre Executable by Group
cecho gre ================================================================================
for f in $(find . -maxdepth 1 -perm -g=x); do
if [[ -f $f && ! -L $f ]]; then
echo --------------------------------------------------------------------------------
ls -al $f
echo
read -p "[i]gnore rule, [r]remove Exec group, [s]kip, q[uit]. [irSq]?: " opt
case $opt in
r|R)
chmod g-x $f;;
i|I)
break;;
q|Q)
exit;;
esac
fi
done
cecho gre ================================================================================
cecho gre No header
cecho gre ================================================================================
for f in $(find . -maxdepth 1 -executable); do
if [[ -f $f && ! -L $f ]]; then
l1="$(cat $f | sed -n '1p')"
l2="$(cat $f | sed -n '2p')"
if [[ "$l1" == "#!/usr/bin/env bash" && "${l2:0:10}" != "help_text=" ]]; then
echo --------------------------------------------------------------------------------
ls -al $f
echo
head -15 $f
echo
read -p "[i]gnore rule, [a]dd header, edit [v]im, edit [c]ode, [s]kip, q[uit]. [iavcSq]?: " opt
case $opt in
a|A)
tidytmp="/tmp/tidy.tmp"
echo '#!/usr/bin/env
help_text="
NAME
'${f:2}' - One line description.
USAGE
'${f:2}' [options] <parameters>
OPTIONS
-x
Description...
-h|--help
Show help text.
DESCRIPTION
Description description description description.
AUTHOR
mjnurse.github.io - 2025
"
help_line="'tbc'"
web_desc_line="'tbc'"
try="Try ${0##*/} -h for more information"
tmp="${help_text##*USAGE}"
usage=$(echo "Usage: ${tmp%%OPTIONS*}" | tr -d "\n" | sed "s/ */ /g")
if [[ "$1" == "" ]]; then
echo "${usage}"
echo "${try}"
exit 1
fi
case $1 in
-h|--help)
echo "$help_text"
exit
;;
esac
' > $tidytmp
tail +2 $f >> $tidytmp
cp -f $tidytmp $f
;;
v|V)
vgim $f
;;
c|C)
code $f
;;
i|I)
break
;;
q|Q)
exit
;;
esac
fi
fi
done