思路:以扩展名作为关联数组的下标,遍历ls的输出,给对应的扩展名+1,最后输出结果。
首先声明一个关联数组:
declare -A exnames;
ls得到的结果不全是文件,需要使用grep将文件类型的行提取出来,并使用awk得到文件名:
names=$( ls -al ${dir}|grep "^-"|awk '{for(i=9;i<=NF;i++){print $i}}');
为了正确地取出扩展名(有的文件名中含有多个点,如org.eclipse.java.xml),需要从左向右进行匹配,匹配到最后一个点为止。需要使用shell中提供的 ##操作符,该操作符为从左到右的贪婪匹配,操作的结果是将匹配到的字符串删除,如
file_name=”com.java.xml”
echo ${file_name##*.}
将会输出xml
不同的大小写将会干扰统计,所以使用如下语句将扩展名全部统一为小写:
line=`tr '[A-Z]' '[a-z]'<<<"$line"`
此外,考虑到以 . 开头的文件名代表隐藏文件,将不会纳入计算。为此,在遍历文件名时,首先判断(1)该文件名是否含有.号(2)该文件名不能以.号开头,代码如下:
tp=`grep "\." <<<"${line}"`;
rtnval1=$?;
tp=`grep "^\." <<<"${line}"`;
rtnval2=$?;
if [ $rtnval1 -eq 0 ] && [ $rtnval2 -ne 0 ] #determine whether there is . in current line
then
ex=${line##*.};
exnames[${ex}]=`expr 1 + ${exnames[${ex}]}`;
fi
然后再提取扩展名进行数量的计算。当然,使用关联数组前,先进行了初始化 。
最后,实现了一个简单的循环将数组中的内容打印出来。
最后完整的脚本如下:
dir=$1;
declare -A exnames;
#names=$(ls -1 ${dir});
names=$( ls -al ${dir}|grep "^-"|awk '{for(i=9;i<=NF;i++){print $i}}');
for line in ${names}
do
line=`tr '[A-Z]' '[a-z]'<<<"$line"`;
tp=`grep "\." <<<"${line}"`;
rtnval1=$?;
tp=`grep "^\." <<<"${line}"`;
rtnval2=$?;
if [ $rtnval1 -eq 0 ] && [ $rtnval2 -ne 0 ] #determine whether there is . in current line
then
ex=${line##*.}; #find extension
exnames[${ex}]=0;
fi
done
### count the extensions
for line in ${names}
do
line=`tr '[A-Z]' '[a-z]'<<<"$line"`;
tp=`grep "\." <<<"${line}"`;
rtnval1=$?;
tp=`grep "^\." <<<"${line}"`;
rtnval2=$?;
if [ $rtnval1 -eq 0 ] && [ $rtnval2 -ne 0 ] #determine whether there is . in current line
then
ex=${line##*.};
exnames[${ex}]=`expr 1 + ${exnames[${ex}]}`;
fi
done
function printArrWithDot()
{
if test ${#exnames[@]} -eq 0
then
echo No files with extensions;
else
for index in ${!exnames[*]}
do
echo -e "EX: .${index} \tCount: ${exnames[${index}]}";
done
fi
}
echo ;
echo ===== Numbers of different extensions:=====
printArrWithDot;
本文永久更新地址://m.ajphoenix.com/linux/25647.html