修复 Linux 文件名的脚本

肯定还有bug,欢迎指正。;-)

(下面的语法加亮有问题。。。)
[bash]

!/bin/bash

posix_chars=”a-zA-Z._0-9-“
bad_chars=”][|#?><*$'"(){}&"

onlyquery=0
only_print=0
only_posix=0
only_whitespace=0
replace_char='
'
append_chars="_2"
remove_dup_underscores=0
allow_recursion=0
start_with_dash=0

function test_name
{
if [ $only_posix -eq 0 ]
then
test_chars="[${bad_chars}]"
ret=0
while(($#!=0))
do
ret=$(($(echo "$1" | wc -l)-1))
echo "$1" | perl -n -l -e "exit 1 if m/[s]/;"
ret=$(($ret+$?))
case "$1" in
"" | - | ${test_chars}) ret=$(($ret+1))
;;
"\") ret=$(($ret+1)) #'' is special !!
;;
esac
shift
done
else
test_chars="[!$posix_chars]"
ret=0
while(($#!=0))
do
case "$1" in
"" | -
| ${test_chars}) ret=$(($ret+1))
;;
esac
shift
done
fi
return $ret
}

function goodname
{
rpl="${2:-
}"
tmp=$(echo -n "$1" | tr '[ trn]' "$rpl")
if [ $only_whitespace -eq 0 ]
then
echo $(echo "$tmp" | sed -e "s/[$bad_chars]/$rpl/g" | sed -e "s/[]/$rpl/g")
fi
}

function nodupunderscore
{
echo "$(echo "$1" | sed -e 's/_
*/
/g')"
}

assume in pwd directory

get_new_name bad_name replace_char append

function get_new_name
{
if test_name "$1"
then
if [ $remove_dup_underscores -eq 1 ]
then
echo "$(no_dup_underscore "$1")"
else
echo "$1"
fi
return
fi
apd="$3"
new_name="$(good_name "$1" $2)"
if [ $remove_dup_underscores -eq 1 ]
then
new_name=$(no_dup_underscore "${new_name}")
fi
if [ -e "${new_name}" ]
then
if [ ${new_name##.} = ${new_name} ]
then
echo "${new_name%.
}${apd}"
else
echo "${new_name%.}${apd}.${new_name##.}"
fi
else
echo "${new_name}"
fi
}

function print_version
{
echo "Copyright (C) WANG Cong, 2008."
echo "Version 1.5"
}

function print_help
{
prog=$(basename $0)
cat <&2
echo >&2
print_help >&2
return 1
fi
test_name “$@”
return $?
else
if [ $only_print -eq 0 ]
then
[ -e “$1” ] || (echo “No such file or directory.” >&2 && return 2)
fi
last_name=$(get_new_name “$1” “${replace_char}” “${append_chars}”)
if [ $only_print -eq 1 ]
then
if [ $allow_recursion -eq 1 ]
then
echo “-p conflicts with -r.” >&2
print_help >&2
return 3
else
echo “$last_name”
fi
else
[ “$1” != “$last_name” ] && mv “$1” “$last_name”
if [ $allow_recursion -eq 1 ]
then
if [ ! -d “$last_name” ]
then
echo “$1”” was not a directory!” >&2
return 4
fi
(cd “$last_name”
ls | while read file
do
echo “$file”
if [ -d “$file” ]
then
main “$file”
else
allow_recursion=0
main “$file”
fi
done)

        fi
    fi
fi
return 0

}

while getopts “rvhsuoqx:a:c:p” var
do
case $var in
v)
print_version
exit 0
;;
h)
print_help
exit 0
;;
c)
replace_char=$OPTARG
if [ ${#OPTARG} -ne 1 ]
then
echo “-c must be followed by a char.” >&2
print_help
exit 1
fi
;;
a)
append_chars=$OPTARG
;;
q)
only_query=1
;;
p)
only_print=1
;;
o)
only_posix=1
;;
r)
allow_recursion=1
;;
u)
remove_dup_underscores=1
;;
s)
only_whitespace=1
;;
x)
start_with_dash=1
tmp=$OPTARG
;;
*)
echo “Bad options!” >&2
print_help
exit 1
esac
done

shift $(($OPTIND - 1))
if [ $start_with_dash -eq 0 ]
then
main “$@”
else
tmp=$(perl -e ‘$foo=”‘“$tmp”‘“;$bar=$foo;$foo=~s/^-*//;rename(“$bar”, “$foo”);print $foo;’)
main “$tmp”
fi
exit $?

[/bash]