CSV to .env Converter
A CSV to .env converter turns rows into environment variables for dotenv, docker compose or a systemd EnvironmentFile. This one builds legal uppercase names from your headings, catches the collisions that would silently overwrite a variable, and quotes with single quotes so a value containing a dollar sign arrives intact rather than expanded. Nothing is uploaded.
Need to pick out one row or a few columns first? Open the app
The quote that does not interpolate
Say a password is p$4ssw0rd. Written with double quotes:
DB_PASSWORD="p$4ssw0rd"
a shell that sources this expands $4 as a positional parameter, which is almost certainly empty, and your password becomes pssw0rd. Some dotenv libraries do their own expansion and behave the same way. Nothing errors; the connection just fails with a wrong password.
Single quotes are the fix. Inside them nothing at all is interpolated: no $VAR, no ${VAR}, no backtick command substitution, no backslash escapes. What you wrote is what you get, in dotenv, in docker compose and in a shell.
DB_PASSWORD='p$4ssw0rd'
So single quotes are used wherever quoting is needed. The exception is a value that itself contains a single quote, which cannot live inside single quotes at all. Those fall back to double quotes with the dollar signs, backticks and backslashes escaped individually, which is more fragile and is the only option available.
A value with no whitespace, no hash and no shell metacharacter needs no quotes and does not get any, so an ordinary file stays readable.
Names, and the collision nobody sees
An environment variable name is letters, digits and underscores, and it cannot start with a digit. Uppercase is not a rule but it is close to universal, so it is the default here.
Column headings do not respect that. order id becomes ORDER_ID, cpu-limit becomes CPU_LIMIT, and 2024 total becomes _2024_TOTAL, since a leading digit is illegal.
Which produces the failure worth naming. user-id and user_id both want to become USER_ID. In an environment, the second assignment simply replaces the first. There is no error, no warning and no way to notice afterwards, because the environment only ever had one variable.
Collisions are detected here and the later name gets a numeric suffix, with the count reported. Conversion time is the only place that mistake is visible.
Keys are built as an optional prefix, then a row key, then the column name. With a prefix of APP and a name column, you get APP_BILLING_API_REPLICAS. When you take only the first row, the row key is left out entirely, so a single-configuration file reads APP_REPLICAS, which is what you actually want.
A worked example, and what .env cannot do
One row of settings:
log level,timeout,db password,note
info,30,p$4ssw0rd,two words
With first-row-only and no prefix:
# 1 row as environment variables
# Every value is a string. .env has no types, no nesting and no arrays.
LOG_LEVEL=info
TIMEOUT=30
DB_PASSWORD='p$4ssw0rd'
NOTE='two words'
LOG_LEVEL and TIMEOUT need no quotes. The password and the two-word note get single quotes. And TIMEOUT=30 is the string 30, not the number: environment variables have no types, so every consumer parses it back itself.
That is the limitation worth stating plainly. A .env file has no types, no nesting and no arrays. Everything is a string. A list has to become a delimited string that something splits later, and a nested structure has to become flattened keys. If your configuration genuinely nests, TOML or YAML is the better target.
Line breaks become \n escapes with a note, because the answer depends on the reader: dotenv and docker compose read the escape back as a newline, a plain shell source keeps the two characters. That matters if you are putting a PEM key in there.
One last thing: a .env file is usually secrets. Nothing here is uploaded, and the file you download should not be committed.
Questions
Why single quotes rather than double?
Because nothing at all is interpolated inside single quotes. A value of $HOME or `date` or ${VAR} stays exactly those characters, in dotenv, in docker compose and in a shell that sources the file. Double quotes interpolate, so a password containing a dollar sign would be silently mangled. Double quotes are used only when the value itself contains a single quote, and then the dollar signs, backticks and backslashes inside are escaped.
What makes a legal variable name?
Letters, digits and underscores, not starting with a digit. Anything else in a column heading becomes an underscore, and uppercase is applied by default because that is the near-universal convention. A heading like order id becomes ORDER_ID, and 2024 total becomes _2024_TOTAL, since a name cannot begin with a digit.
What if two headings produce the same variable name?
The second gets a numeric suffix and the count is reported. user-id and user_id both want to become USER_ID, and in an environment the second assignment simply overwrites the first with no warning from anything. Catching it at conversion time is the only place it is visible.
Can it write more than one row?
Yes, and by default it does, putting the row key into each variable name so the values do not collide. A .env file usually holds a single configuration though, so there is a first-row-only option for that case, and a note when you are writing several rows in case that was not what you meant.
How are line breaks handled?
As a backslash-n escape, and the count is reported, because the answer differs by consumer. dotenv and docker compose read the escape back as a real newline. A plain shell source of the file does not: it keeps the two characters. If you need a genuine multi-line value such as a PEM key, check what will read the file before relying on it.
What does the export option do?
It prefixes every line with export, which makes the file work when you source it in a shell and want the variables passed to child processes. dotenv libraries and docker compose ignore the prefix, so it is harmless there. Leave it off for a file that is only read by an application.
Is there a standard for .env files?
No. What is common to dotenv, docker compose and systemd EnvironmentFile is KEY=value with no spaces around the equals sign, legal variable names, and quoting once a value contains whitespace or a hash. Beyond that they disagree about multi-line values, variable expansion and comments. This writes the shared core, which is what every one of them reads.
Related
Convert your CSV to a .env file
No sign-up, no upload, no row cap. Legal names, collisions caught, and quotes that leave your dollar signs alone.
Back to the converter