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
フォルダリストを配列に配置し、ループ内で1つずつ作成することを避けるために、この問題を解決したいと思います。疑似コードでは、アイデアは次のとおりです。
find "$HOME" -maxdepth 1 -type d | jq '.logic-to-create-json-strings'
それを使用できますかjq
?
答え1
この回答では、ファイル名(またはJSONエンコードするテキスト)が有効なUTF-8であると想定しています。
2つのオプション:
使用しない: 位置引数として pathname をxargs
直接呼び出します。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
withを使用して、xargs
見つかったパス名を安全に渡します。パス名が間に渡される方法が異なる点を除いて、式は上記と同じです。find
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
.
たとえば、ファイルパスはUTF-8でエンコードされ、ISO-8859-1でエンコードされます$'/home/St\xc3\xa9phane\nChazelas/ISO-8859-1/R\xe9sum\xe9'
(ここではバイト値を表すためにksh93
-style$'...'
表記が使用されます)。é
Stéphane
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エンコーディングと見なされる2番目の方法では、次のことができます。
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バイトに対応することがわかります。代わりに、ASCII以外の文字を表す-a
オプションを追加できます。jq
\uXXXX