Shell脚本攻略读书笔记之文件类型统计【Enumerating file type statistics】
1.需求
统计某个路径下的类型文件的数目
2.代码
#!/bin/bash
# Filename: filestat.sh
if [ $# -ne 1 ];
then
echo "Usage is $0 basepath";
exit
fi
path=$1
declare -A statarray;
while read line;
do
ftype=`file -b "$line" | cut -d, -f1`
let statarray["$ftype"]++;
done< <(find $path -type f -print)
echo ============ File types and counts =============
for ftype in "${!statarray[@]}";
do
echo $ftype : ${statarray["$ftype"]}
done
3.运行结果
[root@server4 shells]# ./filestat.sh /root/shells/
===file type and counts=====
POSIX shell script:1
Bourne-Again shell script:15
ASCII text:13
empty:5
UTF-8 Unicode text:1
a /usr/bin/expect script:1
4.分析
- 查看文件类型:
file filename
options
-b --brief :Do not prepend filenames to output lines(brief mode).
如下两种使用方式是一样的,example:
gzip compressed data, from Unix, last modified: Sun Jul 8 06:25:43 2018
[root@server4 ~]# file -b zookeeper-3.4.11.tar.gz
gzip compressed data, from Unix, last modified: Sun Jul 8 06:25:43 2018
- 声明一个数组变量
declare -A
-A :The action may be one of the following to generate a list of possible completions
这个参数可能是以下动作之一,为了生成一个可能完成的列表。【这里略去以下动作】
But, we are not interested in all of the details;we need only the basic information.Details are comma-separated,as in the following example.
- cut 命令
-d, --delimiter=DELIM
use DELIM instead of TAB for field delimiter 【使用DELIM而不是tab作为域分割】
-f, --fields=LIST
select only these fields; also print any line that contains no delimiter character, unless the -s option is specified
【仅仅选择某些域;也可以输出任何不包含分隔符的字符,除非-s选项被指定。】
Bourne-Again shell script, ASCII text executable
[root@server4 shells]# file -b reboot.sh | cut -d,
cut: you must specify a list of bytes, characters, or fields
Try 'cut --help' for more information.
[root@server4 shells]# file -b reboot.sh | cut --delimiter=, -f1
Bourne-Again shell script
[root@server4 shells]# file -b reboot.sh | cut --delimiter=, -f2
ASCII text executable
[root@server4 shells]# file -b reboot.sh | cut --delimiter=, -f3
#【如果没有内容,则不输出】
is an important bit of code.
我怀疑你犯了一个错误:你以为/bin/sh在任何地方都是bash。一些Linux发行版使用更加简单的shells(诸如dash,或者是ksh)作为/bin/sh;如果你想使用bash-具体的扩展诸如<(pipeline)语法,你应该明确地使用bash作为shell。
A while loop is used to iterate line by line through the find command’s output.
一个while循环用于逐行遍历find命令的输出
[root@server4 shells]# find /root/shells/ -type f -print
/root/shells/checkUser.sh
/root/shells/checkZookeeper.sh
/root/shells/reboot.sh
/root/shells/jps.sh
/root/shells/addScalaHome.sh
/root/shells/adjustSysctlConf.sh
/root/shells/closeZookeeper.sh
/root/shells/hosts
/root/shells/startZookeeper.sh
/root/shells/jps.sha1
/root/shells/file1.txt
/root/shells/file2.txt
/root/shells/sorted.txt
/root/shells/isSorted.sh
/root/shells/data.txt
/root/shells/checkword.sh
/root/shells/interactive.sh
/root/shells/input.data
/root/shells/automate_expect.sh
/root/shells/data1.txt
/root/shells/data2.txt
/root/shells/log.txt
/root/shells/filestat.sh
/root/shells/remove_duplicates.sh
/root/shells/server.log
/root/shells/allTableInextractdb.sql
/root/shells/sorted.txt~
/root/shells/a.txt
/root/shells/createFile.sh
/root/shells/1.txt
/root/shells/2.txt
/root/shells/3.txt
/root/shells/file
/root/shells/file1.txt~
/root/shells/filestat.sh.bak
/root/shells/filestat.sh_20181006
这个find命令的输出是作为循环的输入。
正常的while循环是:
while read line;
do something
done < filename
Instead of the filename we used the output of find.<(find $path -type f -print) is equivalent to a filename.
The first < is for input redirection and the second < is for converting the subprocess output to a filename.There is a space between these two.
#!/bin/bash
#Filename:filestat.sh
if [ $# -ne 1 ]; #如果参数不等于1
then
echo "Usage is $0 basepath";
exit
fi
path=$1 #将参数赋值给path
declare -A statarray; #声明一个变量
while read line;
do
#echo ++++++$line is ++++++
ftype=`file -b "$line" | cut -d, -f1` #得出文件的类型
let statarray["$ftype"]++; #将文件类型作为下标,然后自加
done < <(find $path -type f -print)
echo ===file type and counts=====
for ftype in "${!statarray[@]}";
do
echo $ftype:${statarray["$ftype"]}
done
${!statarray[@]}
用于返回数组索引清单
添加类型输出信息后:
[root@server4 shells]# ./filestat.sh /root/shells/
===file type and counts=====
POSIX shell script Bourne-Again shell script ASCII text empty UTF-8 Unicode text a /usr/bin/expect script
POSIX shell script:1
Bourne-Again shell script:15
ASCII text:13
empty:5
UTF-8 Unicode text:1
a /usr/bin/expect script:1