从下面的代码中,我遍历每个文件并检查我的文件名是否匹配小写和特殊字符,并检查它是否少于 20 个字符,但显然我的 if 子句似乎不起作用。有人可以建议吗?
#/bin/bash
Count=$(find . -type f | wc -l)
echo $Count
if [[ ( $Count -ge 2 ) && ( $count -lt 1000 ) ]]
then
for file in *;
do
if [[ $file == [a-z0-9._-] && ${#file} -le 20 ]];
echo "inside if $file ${#file}"
then
[ -f "$file" ] || continue
#Check the extension of the file
ext="${file##*.}"
#check if the file name is ending with .txt push to text directory
if [ $ext == "txt" ]
then
mkdir -p text
mv $file text
fi
#if bash scripts are there push to scripts directory
if [ $ext == "sh" ]
then
mkdir -p Scripts
mv $file Scripts
fi
#if log scripts are there push to log directory
if [ $ext == "log" ]
then
mkdir -p logs
mv $file logs
fi
#if music files are there push to music directory
if [[ $ext == "mp3" || $ext == "flac" ]]
then
mkdir -p Music
mv $file Music
fi
fi
done
fi
答案1
这里有几个小语法问题(其中大部分shellcheck.net会指出——推荐!),但让我从最大的问题开始:
if [[ $file == [a-z0-9._-] && ${#file} -le 20 ]];
echo "inside if $file ${#file}"
then
...
这里的第一个问题是 glob 模式[a-z0-9._-]
匹配单个字符。如果文件名长度超过一个字符,则不会匹配。如果您想确保文件名仅包含该集中的字符,请改用正则表达式测试:($file =~ ^[a-z0-9._-]+$
请注意,在[[ ]]
表达式内部=
进行==
glob 模式匹配,并=~
进行正则表达式匹配)。您还可以将长度检查滚动到此中$file =~ ^[a-z0-9._-]{1,20}$
({1,20}
意思是“前一个事物的 1 到 20 之间”)。
if
第二个问题是,当和之间有多个命令时then
,它的状态是最后一个确定表达式是否被视为 true 或 false。该echo
命令几乎总是成功,因此表达式为真,并且该then
子句几乎总是被执行。我建议要么将其移到echo
其他地方,要么完全删除它。
现在,对于小问题:shebang(第一行)应该以 开头#!
,而不仅仅是#
。Count
和count
是不同的变量(大小写很重要!)。在[ ]
测试中,您应该用双引号变量来避免奇怪的解析,并且==
这是非标准的,因此例如使用[ "$ext" = "txt" ]
而不是[ $ext == "txt" ]
.另外,您应该在其他任何地方都使用双引号变量,例如echo "$Count"
和mv "$file" text
。
最后,我很想用一条语句替换提取扩展名的部分,然后使用if
基于它的一系列语句case
(这几乎就是case
预期的目的):
case "$file" in
*.txt )
mkdir -p text
mv "$file" text ;;
*.sh )
mkdir -p Scripts
mv "$file" Scripts ;;
*.log )
mkdir -p logs
mv "$file" logs ;;
*.mp3 | *.flac )
mkdir -p Music
mv "$file" Music ;;
esac