我正在尝试索引我的文件系统。我想要做的是:执行命令find
,并为每个条目保存上次访问时间、上次修改时间、计算哈希值和其他操作。为了做到这一点,我想执行以下命令:
find . -printf 'PATHNAME=%p -- NAME=%f -- SIZE=%s -- LAT=%a -- LCT=%c -- LMT=%t \n' -exec file {} \; -exec md5sum {} \;
输出类似于:
PATHNAME=./script -- NAME=script -- SIZE=807 -- LAT=Fri Apr 15 16:39:52.0874615579 2016 -- LCT=Tue Apr 12 12:20:57.0767950320 2016 -- LMT=Tue Apr 12 12:20:57.0767950320 2016 <br>
./script: ASCII text <br>
cf1b934c226b194bee96106ea3f019a4 ./script
现在我想获取所有这些参数(例如用 解析它们awk
)并将它们放在某个地方(例如数据库中)。所以,我的问题是:我每次如何将这 3 行重定向到脚本进行解析?有没有更好的方法来编写命令?
答案1
我会使用类似这样的东西(没有数据库中的插入部分)
while read EMPTY_LINE; do
read FILE_SIZE
read FILE_AT
read FILE_MT
read FILE_CT
read MIME_INFO
read HASH FILE_PATH
echo
echo 'File path: '"$FILE_PATH"
echo 'File size: '"$FILE_SIZE"
echo 'File times (access - modified - changed): '"$FILE_AT - $FILE_MT - $FILE_CT"
echo 'MIME stuff: '"$MIME_INFO"
echo 'Hash: '"$HASH"
done < <(find . -type f -printf '\n' -exec stat --printf '%s\n%X\n%Y\n%Z\n' {} \; -exec file -b {} \; -exec md5sum {} \; )
好的,那么这里究竟发生了什么,以及我为什么要这样做?
查找命令
find . -type f -printf '\n' -exec stat --printf '%s\n%X\n%Y\n%Z\n' {} \; -exec file -b {} \; -exec md5sum {} \;
首先执行命令。
让我们详细分析一下。
find .
.
在(当前目录)中查找内容
-type -f
仅查找文件
-printf '\n'
为每个文件匹配打印一个空文件
-exec stat --printf '%s\n%X\n%Y\n%Z\n' {} \;
执行 stat 命令打印几个我自己指定的文件统计信息 - 请参阅stat --help
可用的统计信息
-exec file -b {} \;
执行文件命令来确定 MIME 信息。-b
确保文件名不会随之打印。无论如何我们都会忽略它。
-exec md5sum {} \;
执行md5sum命令计算文件内容的md5哈希值。
一切顺利。-exec
参数按指定的顺序处理。这意味着每个文件匹配,我们将得到以下几行:
[FILE SIZE - from stat command]
[FILE LAST ACCESS TIME - from stat command]
[FILE LAST MODIFICATION TIME - from stat command]
[FILE LAST CHANGE TIME - from stat command]
[MIME INFO - from file command]
[HASH - from md5sum command] [FILE PATH - from md5sum command]
让我们尝试一下该find
命令,看看它是否按照我们预期的那样输出所有内容。
[~/somedir]:$ find . -type f -printf '\n' -exec stat --printf '%s\n%X\n%Y\n%Z\n' {} \; -exec file -b {} \; -exec md5sum {} \;
1752
1441609114
1441609114
1441609114
ASCII text
4fb6f64ce9d07be553a81644b17fe69b ./README.md
./tuptime-install.sh
1649
1441609114
1441609114
1441609114
Bourne-Again shell script, ASCII text executable
9ee7ad860bfa049d1d5f589fba218c6a ./tuptime-install.sh
处理线条
解析这些内容时,有很多地方可能会出错。如果文件名中有空格怎么办?或者其他奇怪的字符怎么办?或者其他参数中也有空格怎么办?为了解决这个问题和其他问题,我明确使用了换行符。这样我们就可以读取整行并进行相应的处理。不需要进行特殊解析。(除了哈希部分,但我们稍后会讲到该部分)
while 循环将输入命令的输出find
。while 循环将在剩下一行时运行。我们读取每个匹配项开头的空行。空行实际上并不是真正需要的,但我们将使用它来保持输出干净。
该脚本非常直观。它按照我们期望的顺序逐行读取行并将其放入变量中。之后,我们将其打印出来。
该命令的工作方式read
是,如果给出了单个变量名,它将把整行读入给定的变量名。如果给出了多个变量,则行将用空格字符(默认情况下)分隔并放入给定的变量中。我们只将它用于命令,因为我们无法指定可以删除文件名的选项。我们可以从' 或md5sum
中获取文件名,但由于 md5sum 出于效率原因没有省略它的选项,因此我们将使用那个。find
stat
我还使用了unixtime
时间戳格式,而不是人类可读的格式。在大多数情况下,如果可能的话,最好以最原始的形式保存数据。
剩下唯一要做的事情就是将数据放入数据库。
脚本输出示例
File path: ./README.md
File size: 1752
File times (access - modified - changed): 1441609114 - 1441609114 - 1441609114
MIME stuff: ASCII text
Hash: 4fb6f64ce9d07be553a81644b17fe69b
File path: ./tuptime-install.sh
File size: 1649
File times (access - modified - changed): 1441609114 - 1441609114 - 1441609114
MIME stuff: Bourne-Again shell script, ASCII text executable
Hash: 9ee7ad860bfa049d1d5f589fba218c6a