WOODY'S
FINDINGS

Scripting recipes

This page offers small scripts using the paths listing feature.
The examples are given with the People files in the Playground.
Here is the JSON version:

{
  "Tom" : {
    "age" : 68,
    "hobbies" : [
      "cooking",
      "guitar"
    ],
    "height" : 175
  },
  "Robert" : {
    "age" : 23,
    "hobbies" : [
      "video games",
      "party",
      "tennis"
    ],
    "running_records" : [
      [
        10,
        12, 9,
        10
      ],
      [ 9,
        12,
        11
      ]
    ],
    "height" : 181
  },
  "Suzanne" : {
    "job" : "actress",
    "movies" : [
      {
        "title" : "Tomorrow is so far",
        "awards" : "Best speech for a silent movie"
      },
      {
        "title" : "Yesterday will never go",
        "awards" : "Best title"
      },
      {
        "title" : "What about today?"
      }
    ]
  }
}

Print all the (path/single value) pairs in the data.

file="~/Desktop/Playground/People.json"
format="json"
scout="/usr/local/bin/scout"

paths=(`scout paths -i $file -f $format --single`)

for path in $paths; do
	echo -n "$path: "
	$scout read -i $file -f $format $path;
done
Output:
Robert.age: 23
Robert.height: 181
Robert.hobbies[0]: video games
Robert.hobbies[1]: party
Robert.hobbies[2]: tennis
Robert.running_records[0][0]: 10
Robert.running_records[0][1]: 12
Robert.running_records[0][2]: 9
Robert.running_records[0][3]: 10
Robert.running_records[1][0]: 9
Robert.running_records[1][1]: 12
Robert.running_records[1][2]: 11
Suzanne.job: actress
Suzanne.movies[0].awards: Best speech for a silent movie
Suzanne.movies[0].title: Tomorrow is so far
Suzanne.movies[1].awards: Best title
Suzanne.movies[1].title: Yesterday will never go
Suzanne.movies[2].title: What about today?
Tom.age: 68
Tom.height: 175
Tom.hobbies[0]: cooking
Tom.hobbies[1]: guitar

About parsing the data

Invoking Scout for each path is not efficient but gives more control. With this example, it's easy to come up with many possibilities to read or modify the data. But if one value has to be set on every path, this flexibility is too expensive to use. It will be possible in a future release to use "batch" functions to run the program only once when the same value has to be set on every path. Meanwhile, it's possible to build the paths and their new values to then provide them to the program, as shown in the last recipe (Suzanne's movies new titles).

Set all "ages" key to 30 in the file People.yml

file="~/Desktop/Playground/People.yml"
format="yaml"
scout="/usr/local/bin/scout"

paths=(`scout paths -i $file -f $format -k "age" --single`)

for path in $paths; do
	$scout set -m $file -f $format "$path=30"
done

Print the paths leading to values lesser than 30

file="~/Desktop/Playground/People.yml"
format="yaml"
scout="/usr/local/bin/scout"

paths=(`$scout paths -i $file -f $format -k "age" --single`)

for path in $paths; do
	value=(`$scout read -i $file -f $format $path`)

	if [ $value -lt 40 ]; then
		echo "$path"
	fi
done

Add a key "language" to all Suzanne's movies with the value "fr" to the file People.plist

file="~/Desktop/Playground/People.plist"
format="plist"
scout="/usr/local/bin/scout"

paths=(`$scout paths -i $file -f $format "Suzanne.movies[:]" --group`)

for path in $paths; do
	$scout add -m $file -f $format "$path.language=fr"
done

Add a key "awards" with a default value if not present in Suzanne's movies array.

file="~/Desktop/Playground/People.xml"
format="xml"
scout="/usr/local/bin/scout"

paths=(`$scout paths -i $file -f $format "Suzanne.movies[:]" --group`)

for path in $paths; do
	if value=$($scout read -i $file -f $format "$path.awards" 2>/dev/null) ; then
		echo "'awards' key found in $path with value '$value'"
	else
		$scout add -m $file -f $format "$path.awards=No awards"
	fi
done

Set Suzanne movies's title to new ones in the file People.plist

file="~/Desktop/Playground/People.plist"
format="plist"
scout="/usr/local/bin/scout"

paths=(`$scout paths -i $file -f $format "Suzanne.movies[:].title"`)
newTitles=("I was tomorrow"  "I'll be yesterday" "I live in the past future")

for ((i=0; i < ${#newTitles[@]} ; i++)); do
	newTitle=${newTitles[$i+1]}
	path=${paths[$i+1]}

	$scout set -m $file -f $format "$path=$newTitle"
done

Same as above but call Scout only once to set the new titles.
file="~/Desktop/Playground/People.plist"
format="plist"
scout="/usr/local/bin/scout"

paths=(`$scout paths -i $file -f $format "Suzanne.movies[:].title"`)
newTitles=("I was tomorrow"  "I'll be yesterday" "I live in the past future")
pathsAndNewTitles=""

for ((i=0; i < ${#newTitles[@]} ; i++)); do
	newTitle=${newTitles[$i+1]}
	path=${paths[$i+1]}
	pathsAndNewTitles="$pathsAndNewTitles '$path=$newTitle'"
done

$scout set -m $file-f $format "$path=$newTitle"