Extract full path in folder-like JSON structure using jq

Viewed 355

I have a JSON file which contains a structure like this:

[
  {
    "name": "folder1",
    "children": [
      {
        "name": "file1",
        "value": "value1"
      },
      {
        "name": "folder2",
        "children": [
          {
            "name": "file2",
            "value": "value2"
          }
        ]
      }
    ]
  },
  {
    "name": "file3",
    "value": "value3" 
  }
]

I want to print full paths and values of every file using jq. For example, with input from above:

folder1/file1 - value1
folder1/folder2/file2 - value2
file3 - value3

Is such thing possible? I haven't found any obvious way to do it, while reading the jq manual and StackOverflow answers about recursive search in jq.

2 Answers

Yes, it is possible. You can use a recursive function like below for achieving this.

def f($path):
  ($path + [.name]) as $path
  | if has("value")
  then "\($path | join("/")) - \(.value)"
  else .children[] | f($path) end;
.[] | f([])

Online demo

Here is a solution which takes advantage of jq's TCO (tail-call optimization) by defining the recursive function as a filter with arity 0 (i.e., no arguments):

# input: [array, $path]
def unwrap:
  .[1] as $path
  | .[0][]
  | if .children then [.children, $path + [.name]] | unwrap
    else [$path + [.name], .value]
    end;

[.] | unwrap | "\(.[0]|join("/")) - \(.[1])"
Related