你好。我知道这里有类似的主题,但说实话我没有找到解决问题的方法。我也检查了 stackoverflow,但没有结果。
我必须编写一个 bash 脚本,该脚本将通过命令行中的参数将文件的名称从小写更改为大写或从大写更改为小写。因此,当我在命令行中输入:
./bashScript 较低 较高
那么目录中的所有文件都应从小写变为大写。
我还必须添加第三个参数,以便只允许我更改一个特定文件。例如,我必须能够在命令行中输入:
./bashScript 下 上 文件名
我创建了类似这样的东西:
#!/bin/bash
if test "$1" = "lower" && test "$2" = "upper"
then
for file in *; do
if [ $0 != "$file" ] && [ $0 != "./$file" ]; then
mv "$file" "$(echo $file | tr [:lower:] [:upper:])";
fi
fi
done
elif test "$1" = "upper" && test "$2" = "lower"
then
for file in *; do
if [ $0 != "$file" ] && [ $0 != "./$file" ]; then
mv "$file" "$(echo $file | tr [:upper:] [:lower:])";
fi
done
fi
但是这个根本不起作用。我不知道如何为一个特定文件创建第三个参数。如果有人能编写代码或在我的代码中添加正确的问题,我将不胜感激。
先感谢您。
答案1
看看这个:
#!/bin/bash
if [[ "$1" == "lower" && "$2" == "upper" ]] ; then
EXPRESSION="y/a-z/A-Z/"
elif [[ "$1" == "upper" && "$2" == "lower" ]] ; then
EXPRESSION="y/A-Z/a-z/"
else
echo "Usage: $0 lower upper [file] OR $0 upper lower [file]"
exit 1
fi
if [[ -z "$3" ]] ; then
shopt -s dotglob
rename "$EXPRESSION" ./*
else
rename "$EXPRESSION" "$3"
fi
通常情况下,你应该使用[[ ... ]]
双括号条件表达式在 Bash 中。在其中,您可以使用例如==
比较字符串相等性(两边都用引号括起来),或者&&
使用逻辑 AND 组合两个条件。
然后,我决定使用rename
命令,而不是使用echo
、tr
和构造的命令mv
。它以“Perl 表达式”作为第一个参数,然后以任意数量的文件名(例如 shell glob 结果)作为第一个参数,并将相应地重命名所有匹配的文件。
将名称中的所有小写字母更改为大写字母的 Perl 表达式是例如y/a-z/A-Z/
。y
是命令,表示转换所有字符。a-z
是与所有小写拉丁字符匹配的符号,A-Z
表示大写。根据脚本参数,我们将转换为大写或小写的表达式存储在 shell 变量中$EXPRESSION
。
然后我们检查是否给出了第三个脚本参数(-z
这是一个 Bash 条件检查,如果字符串为空则为真)。如果没有,我们rename
使用存储的表达式和./*
as shell glob 调用命令来匹配当前目录中的所有文件。dotglob
我们之前启用的 shell 选项确保这也匹配名称以点开头的隐藏文件,否则这些文件将被忽略。但是,如果给出了第三个脚本参数,我们会将其作为参数传递。
答案2
我想我应该发表一下我的看法,对 Byte Commander 的回答稍有不同的看法。
#! /bin/bash
case $1 in
upper)
# check second argument to process a file if one given or the whole directory
if [[ $2 > '' ]] #check if the second parameter is used (filename)
then
if [ -f $2 ] #check if the file exists
then
mv "$2" "$(echo $2 |tr [:lower:] [:upper:])"
else
echo "$2 does not exist"
fi
else
# process the whole directory
for file in *
do
if [ $0 != "$file" ] && [ $0 != "./$file" ]
then
mv "$file" "$(echo $file | tr [:lower:] [:upper:])"
fi
done
fi;;
lower)
# check second argument to process a file if one given or the whole directory
if [[ $2 > '' ]]
then
if [ -f $2 ] #check if the file exists
then
mv "$2" "$(echo $2 |tr [:upper:] [:lower:])"
else
echo "$2 does not exist"
fi
else
#process the whole directory
for file in *;
do
if [ $0 != "$file" ] && [ $0 != "./$file" ]
then
mv "$file" "$(echo $file | tr [:upper:] [:lower:])"
fi
done
fi;;
--help)
echo "Usage: $0 lower to lowercase entire directory "
echo "Usage: $0 uppper to uppercase entire dirctory "
echo "Usage: $0 lower [file] or upper [file] for a specific file"
exit 1;;
esac