To split a large CSV into smaller files on Linux or macOS, use split -l when each record occupies one text line. For example, split -l 100000 filename.csv file_ creates files of up to 100,000 lines. Smaller files can be easier to open in a CSV editor.

Check for line breaks inside quoted fields first. The split command counts text lines, not CSV records, and may cut a record in half. If your CSV has multiline fields, use the CSV Splitter instead. You can count text lines in Terminal to estimate the size of a simple CSV.

macOS and Linux also include the split utility:

split [-l line_count] [-b byte_count] [-n chunk_count] [file [prefix]]

The command split breaks up files using:

  • lines - useful for text-based files
  • bytes - for binary files
  • number - if you want to split a file into a specific number of parts.

CSV is a format for structured text data. For files with one record per line, use split with the line count option. The header counts toward the first file's line limit.

split -l 100000 filename.csv
Basic split CSV file
Basic split CSV file

Split generates files with basic names beginning with x: xaa, xab, xac, etc. See the next section to split your CSV files and rename the generated files.

Using split and renaming generated files

Split has two interesting parameters. The first is -d to use numeric suffixes (1, 2, 3, etc.) instead of letters. The second is the prefix parameter for the generated files. To define the prefix, just add a string after your CSV filename.

split -l 100000 -d filename.csv file_
split CSV file with prefix and numeric suffixes
split CSV file with prefix and numeric suffixes

To give the generated files a .csv extension, rename the parts once:

for part in file_[0-9]*; do
  [ -f "$part" ] || continue
  case "$part" in *.csv) continue ;; esac
  mv "$part" "$part.csv"
done
Renaming generated files with .csv
Renaming generated files with .csv

Adding CSV header to generated files

You have several generated files like: file_00.csv, file_01.csv, etc.

But the CSV header line is on the first file (file_00.csv) and all other files don't have a CSV header line.

Copy the original file's header into each later part. Write to a temporary file first so the shell does not truncate a part while reading it:

header_file=$(mktemp)
head -n 1 filename.csv > "$header_file"
for part in file_*.csv; do
  [ -f "$part" ] || continue
  [ "$part" = "file_00.csv" ] && continue
  temp_file=$(mktemp)
  cat "$header_file" "$part" > "$temp_file" && mv "$temp_file" "$part"
done
rm "$header_file"

The first part already has the header. The remaining parts now have the same columns and can be opened separately. For a file with quoted line breaks, use a CSV-aware splitter instead of these commands.

For quoted multiline CSVs or a browser workflow with header handling, follow how to split a CSV into multiple files. Check overlap and output row counts before importing every part.