introducing iniq


– tags: ini

iniq, a tool that’s a bit like jq

iniq is like jq for INI data. You can use it to format, and filter INI data with ease. It has fewer features than jq though.

iniq is written in Crystal and has no runtime dependencies.

iniq tries to do only one thing and to do it well, in line with the unix philosphy.

Huh!? What is it good for?

War is good for absolutely nothing but iniq is good for fetching values or whole sections from INI files. You may use it for example in shell scripts where you have no INI functions that you would use if you’d chosen to use a “real” programming language.

You may not realise it but INI files are everywhere. For example, they are used by Thunderbird and Firefox including many extensions for those apps. I have 572 ini files on this computer (sudo find / -name \*.ini | wc -l) which is a lot more than I expected.

Besides the obvious files with .ini extension, every PLS playlist is an INI file too and git is using the format extensively for a multitude of config files. Besides those Ansible is using them, .desktop files are INI files, even SystemD scripts follow the same format. I am sure we can find many more.

Invoking iniq

Since the output if iniq is almost always in INI format you can parse this output again with iniq. This means that can chain multiple calls to iniq with pipe operators like this: cat file.ini | iniq "[main]" | iniq "foobar"

Examples

Reformatting an INI file

$ cat .git/config
[core]
  repositoryformatversion = 0
  filemode = true
  bare = false
  logallrefupdates = true
[remote "origin"]
  url = git@github.com:rails/rails.git
  fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
  remote = origin
  merge = refs/heads/master
$ iniq .git/config
[core]
repositoryformatversion=0
filemode=true
bare=false
logallrefupdates=true

[remote "origin"]
url=git@github.com:rails/rails.git
fetch=+refs/heads/*:refs/remotes/origin/*

[branch "master"]
remote=origin
merge=refs/heads/master

Fetching a section

$ iniq .git/config "[core]"
repositoryformatversion=0
filemode=true
bare=false
logallrefupdates=true
$ iniq .git/config "[branch \"master\"]"
remote=origin
merge=refs/heads/master

Fetching one value

$ iniq .git/config "[branch \"master\"]" remote
origin

Values outside of sections

You could have an INI file with no sections, or you need to access values that exist before/outside any section like in this file:

$ iniq /opt/android-sdk/[...]-19/manifest.ini      
name=Glass Development Kit Preview
name-id=google_gdk
vendor=Google Inc.
vendor-id=google
description=Preview of the Glass Development Kit
api=19
revision=5
libraries=com.google.android.glass;
com.google.android.glass=gdk.jar;APIs for Glass Development Kit Preview

If you want to fetch a value that’s not inside any section you can use the pseudo section “[]”

$ iniq /opt/android-sdk/[...]-19/manifest.ini "[]" description
Preview of the Glass Development Kit

or omit the section argument altogether:

$ iniq /opt/android-sdk/[...]-19/manifest.ini description
Preview of the Glass Development Kit

You can also use the psuedo section to fetch all top-level values.

$ iniq /opt/android-sdk/[...]-19/manifest.ini "[]"
name=Glass Development Kit Preview
name-id=google_gdk
vendor=Google Inc.
vendor-id=google
description=Preview of the Glass Development Kit
api=19
revision=5
libraries=com.google.android.glass;
com.google.android.glass=gdk.jar;APIs for Glass Development Kit Preview