split Command in Linux: Complete Guide to Splitting Files into Pieces and Parameters

The `split` command in Linux is used to split large files into smaller parts. It is particularly useful when dealing with large datasets or files that need to be transferred or processed in smaller chunks. The basic syntax of the `split` command is as follows: ``` split [options] input_file [prefix] ``` Here's a table explaining the main parameters and options of the `split` command: | Parameter/Option | Description | |-------------------|----------------------------------------------------------------------------------------------------------------------| | input_file | Specifies the name of the file you want to split. | | prefix | Specifies the prefix for the output files. The split command will generate files with names starting with this prefix followed by a unique identifier. | | -b, --bytes=SIZE | Split the input file into chunks of SIZE bytes. SIZE can be a number followed by a unit suffix (e.g., 100K, 10M). | | -C, --line-bytes=SIZE | Split the input file into chunks of SIZE bytes, but avoid splitting within a line. | | -l, --lines=NUMBER | Split the input file into chunks containing NUMBER lines. | | -a, --suffix-length=N | Use suffixes of length N (default is 2) for the output files. | | --numeric-suffixes | Use numeric suffixes instead of alphabetic. | | --additional-suffix=SUFFIX | Append an additional SUFFIX to the output file names. | Now, let's see some examples of how to use the `split` command: 1. Split a large file into fixed-size chunks (e.g., 100MB each) with numeric suffixes: ```bash split -b 100M large_file.txt chunk_ ``` This will create files named `chunk_aa`, `chunk_ab`, `chunk_ac`, and so on. 2. Split a large file into chunks with a specific number of lines (e.g., 1000 lines each) and numeric suffixes: ```bash split -l 1000 large_file.txt chunk_ ``` This will create files named `chunk_aa`, `chunk_ab`, `chunk_ac`, and so on. 3. Split a large file into fixed-size chunks (e.g., 500MB each) with numeric suffixes and a custom suffix: ```bash split -b 500M --numeric-suffixes --additional-suffix=.part large_file.txt backup_ ``` This will create files named `backup_00.part`, `backup_01.part`, `backup_02.part`, and so on. 4. Split a large file into chunks of 1GB each, but avoid splitting within a line: ```bash split -C 1GB large_file.txt output_ ``` This will create files named `output_aa`, `output_ab`, `output_ac`, and so on, ensuring no line is split between chunks. These are just a few examples of the `split` command usage. Remember to adjust the options according to your specific requirements and file sizes.

I first needed split when I had to email a 4GB database dump to a colleague and the mail server had a 25MB attachment limit. Instead of messing around with a compression tool that still wouldn’t get me under the limit, I split the file into 20MB chunks, sent them one at a time, and had my colleague reassemble them with cat. It felt almost too simple for how well it worked, and I’ve used split for that exact class of problem — breaking large files down for transfer, upload limits, or parallel processing — ever since.

What split Does

split breaks a single file into multiple smaller pieces, either by a fixed number of lines, a fixed byte size, or a target number of output chunks. The pieces can be reassembled later with cat.

split [OPTION]... [FILE [PREFIX]]

If no file is given, split reads from standard input. The default output prefix is x, and by default it splits into files of 1000 lines each, using alphabetic suffixes (xaa, xab, xac, …).

I tested the default behavior:

$ split -l 5 nums.txt part_
$ ls part_*
part_aa  part_ab  part_ac  part_ad

A 20-line file split into 5-line chunks produced four files, each named with a sequential alphabetic suffix.

Core Options and Parameters

-l NUMBER — Split by Number of Lines

split -l 1000 bigfile.txt chunk_

This is the most common mode — split by line count, useful for CSVs, logs, or any line-oriented text data where you don’t want to split a record in the middle.

-b SIZE — Split by Byte Size

split -b 20 nums.txt chunk_

I tested this against a small file and it produced byte-exact chunks, cutting wherever the byte count landed — including potentially mid-line, since -b doesn’t respect line boundaries:

$ split -b 20 -d nums.txt chunk_
$ cat chunk_00
1
2
3
4
5
6
7
8
9
10

SIZE accepts unit suffixes: K, M, G, T (powers of 1024) or KB, MB, GB (powers of 1000). So split -b 500M largefile.iso part_ splits into 500-megabyte chunks.

-C SIZE — Split by Byte Size Without Breaking Lines

This is the option I actually reach for more often than plain -b when working with text files, because it respects line boundaries while still targeting a byte-size ceiling per chunk:

split -C 10M --numeric-suffixes access.log chunk_

Each output file will be at most 10MB, but split won’t cut a line in half to hit that number — it’ll end the chunk at the last complete line before the limit.

-n CHUNKS — Split Into a Specific Number of Files

$ split -n 4 nums.txt piece_
$ ls piece_*
piece_aa  piece_ab  piece_ac  piece_ad

This tells split “I want exactly 4 output files” and it figures out the size per chunk based on the total input size, rather than you specifying the size per chunk yourself. -n supports several sub-modes documented in split --help:

  • N — split into N files based on size of input (may split lines)
  • l/N — split into N files without splitting lines
  • K/N — output only the Kth of N chunks to stdout
  • r/N — round-robin distribution of lines across N files

For example, split -n l/4 data.csv part_ guarantees 4 files without ever cutting a line in half, redistributing byte boundaries as needed to keep lines intact.

-d — Numeric Suffixes Instead of Alphabetic

By default, suffixes are alphabetic (aa, ab, ac…). With -d, you get numeric suffixes starting at 00:

$ split -l 5 -d nums.txt seg_
$ ls seg_*
seg_00  seg_01  seg_02  seg_03

I generally prefer -d for scripting because numeric ordering sorts more intuitively and is easier to iterate over programmatically (seg_00 through seg_99 rather than remembering alphabetic sequencing rules once you pass az).

-x — Hexadecimal Suffixes

Less commonly used, but available for cases needing hex-based naming:

split -l 5 -x nums.txt seg_

-a LENGTH — Suffix Length

Controls how many characters are used in the generated suffix (default is 2, giving up to 676 alphabetic combinations or 100 numeric combinations):

split -l 100 -d -a 4 hugefile.txt part_

With -a 4 and -d, you get up to 10,000 numbered output files (part_0000 through part_9999) — necessary when splitting extremely large files into many small pieces.

--additional-suffix=SUFFIX — Append a File Extension

$ split --additional-suffix=.txt -d -l 5 nums.txt seg_
$ ls seg_*
seg_00.txt  seg_01.txt  seg_02.txt  seg_03.txt

I use this constantly when the split pieces need to retain a recognizable file extension — for instance, splitting a huge .sql dump into pieces that still end in .sql so tooling that inspects file extensions still works correctly.

-e — Elide Empty Output Files

When using -n and the input doesn’t divide evenly, this prevents split from generating empty trailing files.

--filter=COMMAND — Pipe Each Chunk Through a Command

Instead of writing plain files, you can pipe each chunk through an arbitrary shell command, with $FILE representing the intended output filename:

split -l 10000 --filter='gzip > $FILE.gz' access.log part_

This compresses each chunk on the fly as it’s created, which is a huge time-saver when splitting and compressing a large file would otherwise require two separate passes.

How split Works Internally

split reads the input sequentially (it doesn’t need random access, so it works fine on pipes too) and writes to a new output file each time the current chunk’s line count, byte count, or target size is reached. For -l and -C, it scans for newline characters to determine safe cut points. For -n, split needs to know the total input size upfront to calculate even divisions — this generally requires the input to be a seekable regular file rather than a pipe, since split needs to stat() the file to get its size before deciding how to slice it.

Practical, Real-World Examples

1. Splitting a Large File for Email Attachment Limits

split -b 20M largefile.zip part_

Reassemble on the other end with:

cat part_* > largefile.zip

2. Splitting a CSV for Parallel Processing

split -n l/8 --numeric-suffixes=1 -a 2 --additional-suffix=.csv huge_data.csv chunk_
for f in chunk_*.csv; do
  process_data.sh "$f" &
done
wait

This splits into 8 roughly equal chunks without breaking any CSV row, then processes them in parallel across CPU cores — a pattern I’ve used to cut multi-hour ETL jobs down significantly on multi-core servers.

3. Splitting Log Files by Size Before Archiving

split -C 100M --numeric-suffixes --additional-suffix=.log access.log archive_part_
gzip archive_part_*.log

4. Splitting and Compressing in One Pass

split -l 500000 --filter='gzip > $FILE.gz' -d huge_export.csv export_part_

5. Reassembling Split Files

Regardless of how the file was split (by lines, bytes, or chunk count), reassembly is always the same as long as pieces are concatenated in the correct order:

cat part_aa part_ab part_ac > original_file
# or, relying on shell glob ordering:
cat part_* > original_file

I always double-check that shell glob expansion sorts the pieces in the correct order — alphabetic suffixes sort correctly up to 2 characters, but if you used -a 3 or more with a mix of numeric widths, verify with ls part_* first before trusting cat part_* blindly.

split in Shell Scripting and Automation

A pattern I use for distributing work across worker nodes:

#!/bin/bash
INPUT="urls_to_process.txt"
WORKERS=4

split -n l/$WORKERS -d --additional-suffix=.txt "$INPUT" worker_

for f in worker_*.txt; do
  ssh "worker-$(basename "$f" .txt)" "process_urls.sh" < "$f" &
done
wait
echo "All workers finished"

This splits a URL list into N even pieces and dispatches each to a different worker over SSH, running them concurrently — a lightweight alternative to setting up a full job queue for simple parallel batch work.

Comparing split to Related Commands

TaskBest Tool
Splitting a file into piecessplit
Splitting on a specific delimiter pattern (e.g., by section headers)csplit
Extracting a range of linessed -n or head/tail
Combining split pieces backcat
Compressing large files instead of splittinggzip/xz/zstd

split and csplit are often confused. split divides purely by size or count with no awareness of content. csplit divides based on patterns or line numbers you specify (e.g., “start a new file every time you see a line matching ^Chapter“), which is the right tool when you need content-aware splitting rather than purely mechanical splitting.

Troubleshooting Common split Issues

Reassembled file doesn’t match the original — verify the pieces were concatenated in the correct order; use md5sum original_file and cat part_* | md5sum to compare checksums.

-n fails with “cannot determine file size” on a pipe-n (except the r/N round-robin mode) requires a seekable regular file. Write the piped data to a temp file first, then run split -n against that file.

Too many output files hit -a suffix length limits — increase -a to allow more unique suffixes, e.g., -a 4 for up to 10,000 numeric files.

Lines split in half unexpectedly — you used -b (pure byte split) instead of -C (byte split that respects line boundaries). Switch to -C if line integrity matters.

Performance Optimization

split streams input rather than loading the entire file into memory, so it scales well to very large files without excessive RAM usage. For maximum throughput on very large files, -b/-C with a large chunk size (reducing the total number of open()/close() syscalls) is generally faster than a very fine-grained split into thousands of tiny files, since file creation overhead adds up.

Security Implications

Be cautious with --filter, since it passes chunk data through an arbitrary shell command — never use --filter with a command string built from untrusted input, as this creates a command injection risk identical to any other unsanitized shell interpolation.

Compatibility Across Distributions

split is part of GNU coreutils and is available by default on Ubuntu, Debian, Fedora, RHEL/CentOS, Arch, and openSUSE (tested here at coreutils 9.4). BSD/macOS ship a similar but more limited split lacking some GNU extensions like -C, --filter, and --additional-suffix — check split --version (GNU) versus BSD-style man split if writing cross-platform scripts.

split and Disk I/O Behavior

It’s worth understanding what’s actually happening at the system level when split processes a very large file, since this explains both why it’s efficient and where its practical limits lie. split opens the source file once and reads it sequentially in reasonably sized buffered chunks, writing each output file as it goes and closing it once the target line count, byte count, or size threshold is reached. Because it never needs random access into the source file for -l, -b, or -C modes, it can operate on non-seekable input (a pipe) just as well as on a regular file for those modes — the exception being -n, which, as covered earlier, needs to know the total input size up front to divide it evenly, and therefore requires a seekable regular file in most of its sub-modes.

On spinning-disk storage, sequential reads and writes like this are close to the best-case I/O pattern achievable, since the disk head doesn’t need to seek around. On SSDs the distinction matters less, but the sequential access pattern still tends to produce more predictable throughput than something that jumps around the file unpredictably. This is one of the reasons split remains a genuinely fast tool even on very large files — multi-gigabyte ISO images, large database dumps, and massive log archives all split at close to raw disk throughput speed, with split‘s own CPU overhead being close to negligible.

Choosing Between -b, -C, and -n in Practice

New users of split often aren’t sure which of these three sizing modes fits their situation, so it’s worth laying out a clear decision process:

  • Use -b when you have a hard, external byte-size constraint that doesn’t care about content structure — an upload limit, a removable media capacity limit, a fixed-size buffer somewhere downstream. Line integrity doesn’t matter because the consuming system treats the data as an opaque byte stream (e.g., a .tar or .zip archive split for transfer, where the pieces get concatenated back together before ever being interpreted as text).
  • Use -C when you have a similar byte-size constraint, but the content is line-oriented text that must remain valid line-by-line after splitting — CSV exports, log files, or any text format where a downstream tool will try to parse each piece independently rather than only after reassembly.
  • Use -n when your goal isn’t a specific size at all, but rather a specific number of roughly-even pieces — most commonly for distributing work across a known number of parallel workers or CPU cores, where the exact byte size of each piece matters far less than having a predictable, small number of output files.

Verifying Split Output Integrity

For anything beyond casual use, it’s worth building a habit of verifying that reassembly actually reproduces the original file exactly, especially before deleting the original or relying on the split pieces for something important like a backup transfer:

split -b 100M important_archive.tar.gz part_
cat part_* > reassembled.tar.gz
if cmp -s important_archive.tar.gz reassembled.tar.gz; then
  echo "Verified: reassembly matches original exactly"
else
  echo "MISMATCH: reassembled file differs from original" >&2
fi

cmp -s performs a byte-for-byte comparison silently (only exit code, no output), making it a cheap, reliable check to fold into any script that splits a file for transfer and expects to reassemble it later on the receiving end.

Handling Split Files Across a Network Transfer

A pattern I’ve used when transferring split archives to a remote host where bandwidth or connection stability is a concern — transferring each piece individually rather than the whole file allows a failed transfer to be resumed from the last successfully transferred piece, rather than restarting the entire large file from scratch:

split -b 200M large_dataset.tar.gz chunk_
for f in chunk_*; do
  rsync -avz --partial "$f" remote:/data/incoming/
done
ssh remote 'cat /data/incoming/chunk_* > /data/incoming/large_dataset.tar.gz'

Using rsync --partial on each individually split piece, rather than the whole original file, means a dropped connection only costs you the progress on the current chunk, not the entire transfer.

Summary

split turns “this file is too big for X” into a non-problem — whether X is an email attachment limit, an upload size cap, or a desire to parallelize processing across cores or machines. The options that matter most in practice are -l/-C for line-safe splitting, -n for a fixed number of output files, -d for sane numeric ordering, and --filter for compressing on the fly. Once split pieces exist, cat always brings them back together.

References

  • GNU Coreutils Manual — split: https://www.gnu.org/software/coreutils/manual/html_node/split-invocation.html
  • man split (local manual page)
Total
0
Shares

Leave a Reply

Previous Post
sort command in Linux and it perimeters

sort Command in Linux: Complete Guide to Sorting Data, Lines, and Parameters

Next Post
tac command in Linux and it perimeters

tac Command in Linux: Complete Guide to Reverse File Display and Parameters

Related Posts