Bash创建JSON文件清单

Bash创建JSON文件清单,json,bash,md5,manifest,xidel,Json,Bash,Md5,Manifest,Xidel,我有一个bash脚本,可以将带有MD5哈希的文件清单作为JSON输出,如下所示: { 档案:[ { md5:f30ae4b2e0d2551b5962995426be0c3a, 路径:assets/asset_1.png }, { md5:ca8492fdc3547af31afeeb8656619ef0, 路径:assets/asset_2.png }, ] } 它将返回除.gdz之外的所有文件的列表 我使用的命令是: echo{\files\:[$find.-type f-print | gre

我有一个bash脚本,可以将带有MD5哈希的文件清单作为JSON输出,如下所示:

{ 档案:[ { md5:f30ae4b2e0d2551b5962995426be0c3a, 路径:assets/asset_1.png }, { md5:ca8492fdc3547af31afeeb8656619ef0, 路径:assets/asset_2.png }, ] } 它将返回除.gdz之外的所有文件的列表

我使用的命令是:

echo{\files\:[$find.-type f-print | grep-v\.gdz$| xargs md5sum | sed's/\.\/'./'.\xargs printf{\md5\:\%s\,\name\:\%s\},| sed's/,$/']>files.json
但是,当我在生产环境中运行此命令时,它有时会切换MD5哈希和文件路径。我不知道这是为什么,有人知道吗?

< P>你可以考虑使用BASH和GNU工具查找和M5SUM。脚本使用以NUL结尾的路径名并转义相关字符。即使文件名包含换行符,它也应该工作

#!/bin/bash

comma=
printf '{\n  "files": [\n'
while IFS= read -d '' -r line; do
    md5=${line:0:32}
    path=${line:34}
    path=${path//'\'/'\\'}
    path=${path//'"'/'\"'}
    path=${path//$'\b'/'\b'}
    path=${path//$'\f'/'\f'}
    path=${path//$'\n'/'\n'}
    path=${path//$'\r'/'\r'}
    path=${path//$'\t'/'\t'}
    printf '%s%4s{\n%6s"md5": "%s",\n%6s"path": "%s"\n%4s}' \
        "$comma" '' '' "${md5}" '' "${path}" ''
    comma=$',\n'
done < <(find . -type f ! -name '*.gdz' -exec md5sum -z {} +)
printf '\n  ]\n}\n'

我相信这两个脚本都是健壮的,假设最近有GNU工具。

在shell中健壮地执行这一操作有点痛苦;您必须担心文件名中的空格会破坏您当前的代码,正确编码和转义JSON字符串,如果文件名中有引号怎么办?等等

执行相同操作的快速perl脚本,将要扫描的目录作为命令行参数传递:

!/usr/bin/env perl 使用警告; 严格使用; 使用File::Find; 使用Digest::MD5; 使用JSON::PP;或JSON::XS(如果已安装) 我的@hash; 查找\&通缉,@ARGV; 打印JSON::PP->new->ascii->encode{files=>\@hashes}; 通缉犯{ 如果-f$\&&$\\.~/\.gdz$/{ 我的$name=$File::Find::name; $name=~s!^\./!!; 打开my$f,您可以在所有匹配的文件上运行md5sum,然后使用jq执行其余操作:

find.-type f-not-name'*.gdz'-exec md5sum-z{}+\ |jq-slurp-原始输入' { 文件:拆分\u0000 |地图分割 |地图[ .[0], [2:][124;加入 ] |映射{md5:[0],路径:[1]} }' find命令的输出是在所有匹配文件上运行md5sum一次的输出,输出记录用空字节分隔

然后,jq执行以下操作,并且几乎可以肯定地进行优化:

-slurp和-raw输入在任何处理之前读取整个输入 在最外层,我们构建一个以文件为键的对象 split\u0000从空字节分隔的输入记录创建数组 mapsplit将每个数组元素转换为空格上的数组拆分 map[[0],[2:]| join]–为了允许文件名中有空格,我们为每个记录创建一个数组,其中第一个元素是md5哈希,第二个元素是其余元素的串联,即文件名;[2:],因为我们想跳过两个空格 map{md5:[0],path:[1]}将每个两元素数组转换为具有所需键的对象
尝试使用非专用工具创建JSON是一项非常容易出错的任务。请使用专用工具正确创建所需的JSON。我强烈建议:

返回当前目录中的所有文件和目录,并将可选参数$recursive设置为true,同时还包括所有子目录。 [notends with.,/和notends with.,gdz]通过删除目录和gdz文件来过滤file:list的输出。 以字符串和子字符串的形式返回md5sum其标准输出结果。1,32显然返回前32个字符。 x、 .{..}..是一个扩展字符串,其中x有{1+2+3}个元素,例如,计算结果为有6个元素。
这太完美了,谢谢!很高兴知道,谢谢!
#!/bin/bash

printf '{\n  "files": ['
find . -type f ! -name '*.gdz' -exec md5sum -z {} + |
sed -Ez '
s/\\/\\\\/g
s/"/\\"/g
s/\x08/\\b/g
s/\f/\\f/g
s/\n/\\n/g
s/\r/\\r/g
s/\t/\\t/g
s/(.{32})..(.*)/\
    {\
      "md5": "\1",\
      "path": "\2"\
    }/
$!s/$/,/' | tr -d '\0'

printf '\n  ]\n}\n'
xidel -se '
  {
    "files":array{
      for $x in file:list(.,true())[not(ends-with(.,"/")) and not(ends-with(.,"gdz"))]
      return {
        "md5":substring(system(x"md5sum {$x}"),1,32),
        "path":$x
      }
    }
  }
'