Skip to content

Instantly share code, notes, and snippets.

@markusfisch
Last active June 29, 2019 00:58
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save markusfisch/3093736 to your computer and use it in GitHub Desktop.
Save markusfisch/3093736 to your computer and use it in GitHub Desktop.
Remove blanks, convert hypens and underscores and fix extensions in file/directory names
#!/usr/bin/env bash
# Remove blanks
remove_blanks()
{
[[ $N == *[' ']* ]] || return
mv_to "$P/${N// /}"
}
# Convert hypens to underscores
convert_hyphens()
{
[[ $F == *['-']* ]] || return
mv_to "$P/${N//-/_}"
}
# Convert underscores to hypens
convert_underscores()
{
[[ $F == *['_']* ]] || return
mv_to "$P/${N//_/-}"
}
# Make extensions all lower case and fix annoying alternatives
fix_extensions()
{
[[ $N == *.* ]] || return
local E=${N##*.}
local O=$E
# convert upper to lower case
[[ $E == *[ABCDEFGHIJKLMNOPQRSTUVWXYZ]* ]] && E=${E,,}
# fix annoying extensions
case "$E" in
jpeg)
E=jpg
;;
esac
[ "$E" == "$O" ] && return
mv_to "$P/${N%.*}.$E"
}
# Convert to lower case
lower_case()
{
[[ $N == *[ABCDEFGHIJKLMNOPQRSTUVWXYZ]* ]] || return $?
mv_to "$P/${N,,}"
}
# Rename $F to given name
#
# @param 1 - full path with new file name
mv_to()
{
[ "$F" == "$1" ] && return
mv -i "$F" "$1"
F=$1
strip_filename
}
# Strip path and name
strip_filename()
{
P=${F%/*}
N=${F##*/}
}
# Process directories recursively
#
# @param ... - flags and paths
process()
{
local ARG ACTIONS='' DEPTH='-maxdepth 1' DIRS=''
# if the last argument isn't a path, add CWD
for ARG; do true; done
[ -d "$ARG" ] || set -- "$@" '.'
for ARG
do
if [[ $ARG == -* ]]
then
while read -r -n 1
do
[ "$REPLY" ] || continue
case "$REPLY" in
r)
DEPTH=
;;
d)
DIRS=d
;;
b)
ACTIONS=$ACTIONS${ACTIONS:+ }remove_blanks
;;
t)
ACTIONS=$ACTIONS${ACTIONS:+ }convert_hyphens
;;
u)
ACTIONS=$ACTIONS${ACTIONS:+ }convert_underscores
;;
e)
ACTIONS=$ACTIONS${ACTIONS:+ }fix_extensions
;;
l)
ACTIONS=$ACTIONS${ACTIONS:+ }lower_case
;;
*)
echo "error: unknown flag: $REPLY" >&2
return 1
;;
esac
done <<< "${ARG##*-}"
continue
elif ! [ -d "$ARG" ]
then
echo "error: $ARG is not a directory, skipping" >&2
continue
fi
[ "$ACTIONS" ] || {
echo 'error: you need to choose at least one action' >&2
return 1
}
local T F P N A
for T in $DIRS f
do
find "$ARG" "$DEPTH" -type "$T" | while read -r F
do
strip_filename
for A in $ACTIONS
do
"$A" "$F"
done
done
done
done
}
[ "$1" ] || {
cat <<EOF
usage: ${0##*/} [-rbhuel] [PATH]...
-r find files recursively
-d modify directory names also
-b remove blanks
-t convert hyphens to underscores
-u convert underscores to hyphens
-e fix extensions
-l make file name all lower case
EOF
exit
}
if [ "${BASH_SOURCE[0]}" == "$0" ]
then
process "$@"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment