INI to CSV Converter

An INI to CSV converter turns a config file into a spreadsheet: one row per section, one column per key. This one reads the dialects that are actually in the wild, including colon separators, git's quoted subsections and both continuation styles, keeps repeated keys instead of overwriting them, and does not mistake a hex colour for a comment. Nothing is uploaded.

Want to compare two configs side by side? Open the app

Two shapes, because one of them is unusable

An INI file with several sections is obviously row shaped: each section is a record, each key is a field. That comes out as a table with a section column and one column per distinct key across the whole file.

A file with one section is not. Turning it into one row of forty columns produces a spreadsheet you have to scroll sideways through to read a config that fitted on one screen. So a single-section file comes out tall instead, as a two-column key and value table, and you are told why.

A switch forces the key and value shape for multi-section files too, which gives three columns, section, key and value. That is the right shape when you want to diff two configs, filter to the keys you care about, or feed the result into something that expects long rather than wide data.

Sections that define different sets of keys are handled by taking the union in first-seen order, with empty cells where a section does not define a key. Those empties are counted and reported, because a config where staging is missing three keys that production has is usually the thing you were looking for.

A worked example

Two connection profiles:

; Connection profiles

[production]
host = db-prod-01.internal
port = 5432
pool_size = 20
region_code = 01730

[staging]
host = db-staging-01.internal
port = 5432
pool_size = 5
region_code = 00412

becomes:

section,host,port,pool_size,region_code
production,db-prod-01.internal,5432,20,01730
staging,db-staging-01.internal,5432,5,00412

The comment line is gone, the section names are a column, and the region codes keep their leading zeros because everything comes out of an INI file as text.

A git config is read the same way, with one adjustment. Git writes subsections as a quoted string after the section name, and that becomes a dotted name:

[remote "origin"]        →  section = remote.origin
[branch "main"]          →  section = branch.main

which is exactly what git itself calls those key paths when you run git config --list.

The hash that is not a comment

This is the bug worth naming, because it is easy to write and hard to notice. Trailing comments are real: path = C:\tools ; the SDK should give you C:\tools. So a reader strips everything from the comment character onwards.

Then somebody has color = #ff0000 in their file, and the value becomes an empty string. Every hex colour in the config is silently blank, and the config still loads, and everything renders black.

The rule that fixes it is small: a # or ; only starts a trailing comment when whitespace comes immediately before it, and never at the very start of the value. Whole-line comments are handled separately, before a line is ever considered as a key and value pair, so the two cases never interfere. A comment character inside quotes is ignored as well.

The other place data quietly disappears is a repeated key. Most readers keep only the last value, so include = a followed by include = b gives you b and nothing else, even though several dialects use exactly that syntax to express a list. Here the repeats are renamed include_2, include_3 and so on, with a count in the warnings, so both values reach the CSV and you can decide what they meant.

Quoted values have their quotes removed, and a double-quoted value has its \n and \t escapes resolved while a single-quoted one is left literal, which is the convention the dialects that support quoting mostly agree on.

Questions

Why is my colour value not being eaten as a comment?

Because a hash only starts a trailing comment when whitespace comes before it. A value of #ff0000 has the hash at the very start, so it is the value rather than a comment, and treating it otherwise turns every hex colour in a config file into a blank. Whole-line comments are stripped separately, before the value is ever looked at, so the two cases never collide.

What shape does the CSV come out in?

One row per section when the file has several, with a section column and one column per distinct key. When the file has only one section, that would be a single very wide row, which nobody can read, so it comes out as a tall key and value table instead. There is a switch to force the key and value shape when you want it.

Does it read git config files?

Yes. Git writes subsections as a quoted string after the section name, so a remote origin header becomes the section name remote.origin, which is what git itself calls that key path. Ordinary dotted section names come through as they are written.

What happens when a key appears twice in one section?

The repeats are renamed with a numeric suffix and the count is reported. Most INI readers keep only the last value, which silently discards data, and repeated keys are how several dialects express a list. Renaming means both values reach the CSV and you can decide what they meant.

Are colon separators supported?

Yes. Python's configparser accepts a colon as well as an equals sign, and plenty of files in the wild use it, so both are read. Continuation lines are handled too, in both the trailing-backslash style and the configparser style where an indented line under a key extends its value.

What about lines that are not key and value pairs?

A bare word on a line with no separator is skipped, counted and quoted back with its line number. Some dialects treat a lone word as a flag set to true and others treat it as a syntax error, so guessing either way in silence would be wrong. Naming the lines lets you decide.

Is anything uploaded?

No. Parsing runs in your browser tab with nothing sent to a server, nothing kept between visits and no row cap. Config files carry hostnames, ports, usernames and sometimes worse, so keeping them on your machine is the right default.

Convert your INI to CSV

No sign-up, no upload, no row cap. Sections as rows, repeated keys kept, and hex colours that survive.

Back to the converter