# Read a text file line by line

Acquire / file

A variant of [Read another file format](https://meridian.online/operations/read-another-file-format).

Read a text file into a single string column with one row per line.

Page: <https://meridian.online/operations/read-another-file-format/read-a-text-file-line-by-line>

## Status

Runs as a SQL step.

arcform carries it as a `sql:` step today.

## The DuckDB step

read a text file into one string column with a row per line

```sql
-- lines with commas, quotes, a tab, a blank line and non-ASCII text, and a final line with no newline
COPY (SELECT encode('id,name' || chr(10) || '1,"Alice, Ng"' || chr(10) || chr(10) || 'tab' || chr(9) || 'here' || chr(10) || 'Díaz;"x' || chr(10) || 'last'))
  TO '<your_scratch_dir>/text_lines.txt' (FORMAT blob);
CREATE TEMP TABLE result AS
SELECT unnest(arr) AS line, generate_subscripts(arr, 1) AS line_no
FROM (SELECT string_split_regex(regexp_replace(content, '\r?\n$', ''), '\r?\n') AS arr FROM read_text('<your_scratch_dir>/text_lines.txt') WHERE length(content) > 0);
SELECT * FROM result ORDER BY line_no;
SELECT CASE WHEN ((SELECT list(column_name) FROM (DESCRIBE result)) = ['line', 'line_no'] AND (SELECT list(line ORDER BY line_no) FROM result) = ['id,name', '1,"Alice, Ng"', '', 'tab' || chr(9) || 'here', 'Díaz;"x', 'last']) THEN 'as expected' ELSE error('the file did not read as six lines kept as written, including the blank one') END AS verdict;
```

Replace `<your_scratch_dir>` with a directory of your own that you can write to before running the statement.

The statement writes `text_lines.txt` itself, in `<your_scratch_dir>`.

It needs nothing installed beyond DuckDB itself.

## What other tools call it

Meridian's classification; an independent blind rating agreed on 95.7% of 324 rows (variant, version 3).

- EasyMorph: [`Import plain text`](https://help.easymorph.com/doku.php?id=transformations:importplaintext) (read 2026-09-27)
- KNIME Analytics Platform: [`Line Reader`](https://api.hub.knime.com/nodes/*s_Y_nKnj8aCNvqRp?details=full) (read 2026-09-27)
- Apache NiFi: [`TailFile`](https://nifi.apache.org/components/org.apache.nifi.processors.standard.TailFile/) (read 2026-09-27)
- OpenRefine: [`Text files`](https://openrefine.org/docs/manual/starting#create-a-project-by-importing-data) (read 2026-09-27)
- Polars: [`read_lines`](https://docs.pola.rs/api/python/stable/reference/io.html) (read 2026-09-27)
- Polars: [`scan_lines`](https://docs.pola.rs/api/python/stable/reference/io.html) (read 2026-09-27)
- VisiData: [`txt (loader)`](https://github.com/saulpw/visidata/blob/7609212ec2febafa9caba7183cbebfaf49627909/visidata/_open.py#L205) (read 2026-09-23)
