3.10 列举文件类型统计信息
提到文件类型,可谓数量繁多。如果编写一个脚本,使它能够遍历一个目录中所有的文件,并生成一份关于文件类型细节以及每种文件类型数量的报告,这肯定很有意思。这则攻略正是练习如何编写一个能够遍历大量文件并收集详细信息的脚本。
3.10.1 预备知识
find
命令可以通过查看文件内容来找出特定类型的文件。在UNIX/Linux系统中,文件类型并不是由文件扩展名决定的(而在微软Windows平台中正是这么做的)。编写这个脚本的目的是从多个文件中收集文件类型统计信息。我们用关联数组存储相同类型的文件数量,用find
命令获取每一个文件的类型细节。
3.10.2 实战演练
用下面的命令打印文件类型信息:
- $ file filename
- $ file /etc/passwd
- /etc/passwd: ASCII text
打印不包括文件名在内的文件类型信息:
- $ file -b filename
- ASCII text
生成文件统计信息的脚本如下:
#!/bin/bash
# 文件名: filestat.sh
if [ $# -ne 1 ];
then
echo $0 basepath;
echo
fi
path=$1
declare -A statarray;
while read line;
do
ftype=`file -b "$line"`
let statarray["$ftype"]++;
done< <(find $path -type f -print)
echo ============ File types and counts =============
for ftype in "${!statarray[@]}";
do
echo $ftype : ${statarray["$ftype"]}
done
用法如下:
- $ ./filestat.sh /home/slynux/temp
一个简单的输出如下:
- $ ./filetype.sh /home/slynux/programs
- ============ File types and counts =============
- Vim swap file : 1
- ELF 32-bit LSB executable : 6
- ASCII text : 2
- ASCII C program text : 10
3.10.3 工作原理
在脚本中声明了一个关联数组statarray
,这样可以用文件类型作为数组索引,将每种文件类型的数量存入数组。每次遇到一个文件类型,就用let
增加计数。find
命令以递归的方式获取文件路径列表。脚本中的ftype=
使用file \-b "$line"
file
命令获得文件类型信息。选项-b
告诉file
命令只打印文件类型(不包括文件名)。输出的文件类型信息包含很多细节,比如图像编码以及分辨率(如果是图像文件的话)。不过,对于这些细节我们并不感兴趣,我们只需要基本的信息就够了。各种细节信息是由逗号分隔的,例如:
- $ file a.out -b
- ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically
- linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
我们只需要从上面这些细节中提取“ELF 32-bit LSB executable
”。因此我们使用cut -d, -f1
,指明以逗号作为定界符,并且只打印第一个字段。
done<<(find $path -type f -print);
是一段很重要的代码。它的执行逻辑如下:
while
read line;
do
something
done<
filename
我们不用filename
,而是用find
命令的输出。
<(find $path -type f -print)
等同于文件名。只不过它用子进程输出来代替文件名。注意这里还有另外一个 <
。
${!statarray[@]}
用于返回一个数组索引列表。