假设我使用该命令find "$HOME" -maxdepth 1 -type d
并得到以下结果:
/home/user/folder1
/home/user/folder2
/home/user/folder3
/home/user/folder4
我想jq
在管道上使用并创建不同的 JSON 行,如下所示:
{ "path": "/home/user/folder1", "type":"directory"}
{ "path": "/home/user/folder2", "type":"directory"}
{ "path": "/home/user/folder3", "type":"directory"}
{ "path": "/home/user/folder4", "type":"directory"}
我希望解决这个问题,以jq
避免将文件夹列表放入数组中并在循环中一一创建它们。在伪代码中,这个想法是:
find "$HOME" -maxdepth 1 -type d | jq '.logic-to-create-json-strings'
可以用 做吗jq
?
答案1
此答案假设您的文件名(或您希望进行 JSON 编码的任何文本)是有效的 UTF-8。
两种选择:
不使用xargs
:直接从with调用jq
路径名作为位置参数。读取找到的路径名并将其作为表达式中的数组进行访问。对于每个路径名,创建一个 JSON 对象。find
-exec
--args
$ARGS.positional
jq
find "$HOME" -maxdepth 1 -type d \
-exec jq -n -c \
'$ARGS.positional[] as $path | { path: $path, type: "directory" }' \
--args {} +
使用xargs
:使用-print0
withfind
和-0
withxargs
将找到的路径名安全地传递给find
to xargs
。该表达式与上面的相同,只是路径名在和jq
之间传递的方式不同。find
jq
find "$HOME" -maxdepth 1 -type d -print0 |
xargs -0 jq -n -c \
'$ARGS.positional[] as $path | { path: $path, type: "directory" }' --args
使用上述两种方法,jq
都会对找到的路径名进行编码,以便它们可以表示为 JSON 字符串。
另一种jq
表达方式,效果与
$ARGS.positional[] as $path | { path: $path, type: "directory" }
是
$ARGS.positional | map({ path: ., type: "directory" })[]
读书线如您所显示的一组对象,您可以使用以下jq
命令,该命令从其标准输入流读取:
jq -R -c '{ path: ., type: "directory" }'
答案2
JSON 无法直接表示其字符串(UTF-8 编码字符序列)中的任意文件路径(非零的字节序列)。另请注意的输出find
不可后处理除非你使用-print0
.
例如,文件路径可能是$'/home/St\xc3\xa9phane\nChazelas/ISO-8859-1/R\xe9sum\xe9'
(此处使用ksh93
-style$'...'
表示法来表示字节值),其中é
UTF-8 编码为Stéphane
,ISO-8859-1 编码为Résumé
。
JSON 无法表示该文件路径,除非您使用某种编码。例如,这可能是 URI 编码:
{ "path": "/home/St%C3%A9phane\nChazelas/ISO-8859-1/R%E9sum%E9" }
另一种方法可能是将路径解释为 ISO-8859-1 编码(或任何单字节字符集,其中任何字节值都可以构成有效字符):
{ "path": "/home/Stéphane\nChazelas/ISO-8859-1/Résumé" }
jq
对 URI 编码有一些支持,但据我所知不能提供非 UTF-8 输入。 AFAIK,它也不支持任何编码转换。
在 GNU 系统上,对于文件路径被认为是 ISO-8859-1 编码的第二种方法,您可以执行以下操作:
find ~ -type d -print0 |
iconv -f iso-8859-1 -t utf-8 |
tr '\0\n' '\n\0' |
jq -Rc '{"path":sub("\u0000";"\n"),"type":"directory"}'
在我们上面的例子中给出:
{"path":"/home/Stéphane\nChazelas/ISO-8859-1/Résumé.pdf","type":"directory"}
¹ 尽管 iso-8859-1 是一个明显的选择,因为它的代码点与 Unicode 的代码点相匹配。因此,如果您的 json 字符串包含 U+00E9 字符,您就知道它对应于 0xE9 字节。您可以添加-a
选项来代替jq
将非 ASCII 字符表示为\uXXXX
。