Shell 枚举文件类型统计信息

Shell 枚举文件类型统计信息,Linux支持很多文件类型。如果有一个脚本,它能够遍历目录及其子目录中所有的文件,并生成一份关于文件类型细节以及每种文件类型数量的报告,这肯定很有意思。本章将教你编写这样一个能够遍历大量文件并收集相关细节的脚本。

Shell枚举文件类型统计信息

预备知识

在Unix/Linux系统中,文件类型并不是由文件扩展名决定的(微软的Windows操作系统是这么做的)。Unix/Linux系统使用file命令,通过检查文件内容来确定其类型。编写这个脚本的目的是从多个文件中收集文件类型统计信息。脚本利用关联数组保存同类文件的数量信息。

bash在版本4 中才开始支持关联数组

实战演练

按照以下步骤来枚举文件类型统计信息。

(1) 用下面的命令打印文件类型信息:

$ file filename

$ file /etc/passwd
/etc/passwd: ASCII text

(2) 打印不包括文件名在内的文件类型信息:

$ file -b filename
ASCII text

(3) 生成文件统计信息的脚本如下:

# !/bin/bash
# 文件名: filestat.sh

if [ # -ne 1 ];
then
  echo "Usage is0 basepath";
  exit
fi
path=1

declare -A statarray;

while read line;
do
  ftype=`file -b "line" | cut -d, -f1`
  let statarray["ftype"]++;

done<(findpath -type f -print)

echo ============ File types and counts =============
for ftype in "{!statarray[@]}";
do
  echoftype :  {statarray["ftype"]}
done

(4) 用法如下:

$ ./filestat.sh /home/slynux/temp

(5) 输出信息如下:

$ ./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

工作原理

该脚本依赖于关联数组statarray。这个数组用文件类型作为数组索引:PDF、ASCII…。每个索引对应的值是该类型文件的数量。使用命令declare -A statarray定义关联数组。

脚本由两个循环组成:一个是while循环,负责处理find命令的输出;另一个是for循环,用于迭代statarray并生成输出。
while循环的形式如下:

while read line;
do something
done < filename

在这里,我们没有使用文件,而是使用find命令的输出作为while的输入。(find $path -type f -print)就相当于上面的filename(文件名),只不过是用的子进程的输出。

注意,第一个<用于输入重定向,第二个<用于将子进程的输出转换成相应的filename(文件名)(注:这里使用了进程替换)。这两个<之间有一个空格,因此shell并不会将其解释为<<操作符。

find命令使用选项-type f返回$path所定义的目录下的文件列表。read命令一次读取一个文件名。当read接收到EOF(文件末尾)时,它返回假,while命令退出。

while循环中,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。因此使用-d,指明以逗号作为分隔符,使用-f1选择第一个字段。

<(find $path -type f -print)等同于文件名。只不过它用子进程输出来代替文件名。注意,第一个<用于输入重定向,第二个<用于将子进程的输出转换成文件名。在两个<之间有一个空格,避免shell将其解释为<<操作符。

Bash 3.x及更高的版本中,有一个新操作符<<<,可以让我们将字符串作为输入文件。利用这个新操作符,可以将loop循环的done语句改写成:

done <<< "`find $path -type f -print`"

${!statarray[@]}用于返回数组的索引列表。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程