在 Linux 中建立文件索引
Building a file index in Linux
我有一个包含深层嵌套目录的文件系统。在树中任何节点的底层目录中都有一个目录,其名称是数据库中记录的 guid
。此文件夹包含附加到该记录的二进制文件(pdf、jpg 等)。
两个示例路径:
/g/camm/MOUNT/raid_fs0/FOO/042014/27/123.456.789/04.20.30--27.04.2014--RJ123.pdf
/g/camm/MOUNT/raid_fs1/FOO/052014/22/321.654.987/04.20.30--27.04.2014--RJ123.pdf
在上面的例子中,123.456.789
和321.654.987
是guid
s
我想建立一个完整文件系统的索引,这样我就可以在我的数据库中创建一个查找 table 来轻松地将记录的 guid
映射到的绝对路径其附件。
我可以轻松地生成一个直接的文件列表:
find /g/camm/MOUNT -type f > /g/camm/MOUNT/files.index
但我想将每个文件路径的输出解析为 CSV 文件,如下所示:
GUID ABSOLUTEPATH FILENAME
123.456.789 /g/camm/MOUNT/raid_fs0/FOO/042014/27/123.456.789/04.20.30--27.04.2014--RJ123.pdf 04.20.30--27.04.2014--RJ123.pdf
321.654.987 /g/camm/MOUNT/raid_fs1/FOO/052014/22/321.654.987/04.20.30--27.04.2014--RJ123.pdf 04.20.30--27.04.2014--RJ123.pdf
我想我需要将 find 命令的输出通过管道传输到 xargs
,然后再次传输到 awk
,以将输出的每一行处理成 CSV 输出所需的格式...但是我无法让它工作...
我认为没有比您的 find
命令更快的东西了,但是
您可能对 locate 包感兴趣。它使用 updatedb
命令(通常是每晚由 cron 执行 运行)来遍历文件系统并创建一个包含所有文件名的文件,该文件的方式可以通过其他命令轻松搜索。
locate
命令用于读取数据库以查找匹配的目录、文件等,甚至使用 glob 通配符或正则表达式模式匹配。一旦尝试,没有它就很难生活。
例如,在我的系统上 locate -S
列出了统计信息:
Database /var/lib/mlocate/mlocate.db:
59945 directories
505330 files
30401572 bytes in file names
12809265 bytes used to store database
我能做到
locate rc-dib0700-nec.ko
locate -r rc-.*-nec.ko
locate '*/media/*rc-*-nec.ko*'
立即找到 /usr/lib/modules/4.1.6-100.fc21.x86_64/kernel/drivers/media/rc/keymaps/rc-dib0700-nec.ko.xz
这样的文件。
等待你的long-运行 find
完成,然后你
可以通过 awk 传递文件名列表:
awk -F/ '{printf "%s,%s,%s\n",$(NF-1),[=10=],$NF}' /g/camm/MOUNT/files.index
这将转换像
这样的行
/g/camm/MOUNT/raid_fs0/FOO/042014/27/123.456.789/04.20.30--27.04.2014--RJ123.pdf
进入
123.456.789,/g/camm/MOUNT/raid_fs0/FOO/042014/27/123.456.789/04.20.30--27.04.2014--RJ123.pdf,04.20.30--27.04.2014--RJ123.pdf
-F/
将行拆分为字段,使用“/”作为分隔符,NF
是
字段数,所以 $NF
表示最后一个字段, $(NF-1)
next-to-last,这似乎是你想要在第一列中的目录
的输出。我在 printf 中使用“,”来分隔输出列,如
在 csv 中是典型的;您可以将其替换为任何字符,例如 space 或“;”。
您几乎可以使用 find
的 -printf
选项做您想做的事。
难点在于 GUID。
假设前缀的长度与您示例中的长度相同,我可能会这样做:
find /g/camm/MOUNT -type f -printf "%h %p %f\n" | colrm 1 37 > /g/camm/MOUNT/files.index
或者如果/
的数量不变
find /g/camm/MOUNT -type f -printf "%h %p %f\n" | cut -d '/' -f 9- > /g/camm/MOUNT/files.index
否则,我会使用 sed
:
find /g/camm/MOUNT -type f -printf "%h %p %f\n" | sed -e 's@^.*/\(.*\) @ @' > /g/camm/MOUNT/files.index
我有一个包含深层嵌套目录的文件系统。在树中任何节点的底层目录中都有一个目录,其名称是数据库中记录的 guid
。此文件夹包含附加到该记录的二进制文件(pdf、jpg 等)。
两个示例路径:
/g/camm/MOUNT/raid_fs0/FOO/042014/27/123.456.789/04.20.30--27.04.2014--RJ123.pdf
/g/camm/MOUNT/raid_fs1/FOO/052014/22/321.654.987/04.20.30--27.04.2014--RJ123.pdf
在上面的例子中,123.456.789
和321.654.987
是guid
s
我想建立一个完整文件系统的索引,这样我就可以在我的数据库中创建一个查找 table 来轻松地将记录的 guid
映射到的绝对路径其附件。
我可以轻松地生成一个直接的文件列表:
find /g/camm/MOUNT -type f > /g/camm/MOUNT/files.index
但我想将每个文件路径的输出解析为 CSV 文件,如下所示:
GUID ABSOLUTEPATH FILENAME
123.456.789 /g/camm/MOUNT/raid_fs0/FOO/042014/27/123.456.789/04.20.30--27.04.2014--RJ123.pdf 04.20.30--27.04.2014--RJ123.pdf
321.654.987 /g/camm/MOUNT/raid_fs1/FOO/052014/22/321.654.987/04.20.30--27.04.2014--RJ123.pdf 04.20.30--27.04.2014--RJ123.pdf
我想我需要将 find 命令的输出通过管道传输到 xargs
,然后再次传输到 awk
,以将输出的每一行处理成 CSV 输出所需的格式...但是我无法让它工作...
我认为没有比您的 find
命令更快的东西了,但是
您可能对 locate 包感兴趣。它使用 updatedb
命令(通常是每晚由 cron 执行 运行)来遍历文件系统并创建一个包含所有文件名的文件,该文件的方式可以通过其他命令轻松搜索。
locate
命令用于读取数据库以查找匹配的目录、文件等,甚至使用 glob 通配符或正则表达式模式匹配。一旦尝试,没有它就很难生活。
例如,在我的系统上 locate -S
列出了统计信息:
Database /var/lib/mlocate/mlocate.db:
59945 directories
505330 files
30401572 bytes in file names
12809265 bytes used to store database
我能做到
locate rc-dib0700-nec.ko
locate -r rc-.*-nec.ko
locate '*/media/*rc-*-nec.ko*'
立即找到 /usr/lib/modules/4.1.6-100.fc21.x86_64/kernel/drivers/media/rc/keymaps/rc-dib0700-nec.ko.xz
这样的文件。
等待你的long-运行 find
完成,然后你
可以通过 awk 传递文件名列表:
awk -F/ '{printf "%s,%s,%s\n",$(NF-1),[=10=],$NF}' /g/camm/MOUNT/files.index
这将转换像
这样的行/g/camm/MOUNT/raid_fs0/FOO/042014/27/123.456.789/04.20.30--27.04.2014--RJ123.pdf
进入
123.456.789,/g/camm/MOUNT/raid_fs0/FOO/042014/27/123.456.789/04.20.30--27.04.2014--RJ123.pdf,04.20.30--27.04.2014--RJ123.pdf
-F/
将行拆分为字段,使用“/”作为分隔符,NF
是
字段数,所以 $NF
表示最后一个字段, $(NF-1)
next-to-last,这似乎是你想要在第一列中的目录
的输出。我在 printf 中使用“,”来分隔输出列,如
在 csv 中是典型的;您可以将其替换为任何字符,例如 space 或“;”。
您几乎可以使用 find
的 -printf
选项做您想做的事。
难点在于 GUID。
假设前缀的长度与您示例中的长度相同,我可能会这样做:
find /g/camm/MOUNT -type f -printf "%h %p %f\n" | colrm 1 37 > /g/camm/MOUNT/files.index
或者如果/
的数量不变
find /g/camm/MOUNT -type f -printf "%h %p %f\n" | cut -d '/' -f 9- > /g/camm/MOUNT/files.index
否则,我会使用 sed
:
find /g/camm/MOUNT -type f -printf "%h %p %f\n" | sed -e 's@^.*/\(.*\) @ @' > /g/camm/MOUNT/files.index