cut pulls columns out of each line of text. You can select by field with a delimiter, by character position, or by byte. It’s fast and simple, and perfect for structured files like /etc/passwd and CSV exports.

Fields with a delimiter

cut -d: -f1 /etc/passwd            # usernames
cut -d: -f1,7 /etc/passwd          # username and shell
cut -d, -f2 users.csv              # second CSV column
cut -d, -f2-4 users.csv            # columns 2 to 4
cut -d, -f3- users.csv             # column 3 to the end
cut -d' ' -f1 access.log           # first space-separated field (client IP)
  • -d sets the delimiter (one character; default is tab).
  • -f selects fields: 1, 1,3, 2-4, 3-, -2.

Change the output delimiter:

cut -d: -f1,7 --output-delimiter=' -> ' /etc/passwd
# root -> /bin/bash

Characters and bytes

cut -c1-8 file          # first 8 characters of each line
cut -c10- file          # from character 10 onwards
echo "2026-10-14T09:12:00" | cut -c1-10    # 2026-10-14
cut -b1-4 file          # bytes (differs from -c for multibyte text)

Character ranges are useful for fixed-width output, such as dates at a known position in log lines.

Everything except some fields

cut -d, -f2 --complement data.csv      # drop column 2

Lines without the delimiter

By default, lines that don’t contain the delimiter are printed unchanged. Use -s to skip them:

cut -d: -f2 -s file

Practical examples

Users with a login shell:

grep -v -E 'nologin|false' /etc/passwd | cut -d: -f1

Top client IPs (combined with sort and uniq):

cut -d' ' -f1 /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

Just the version number:

nginx -v 2>&1 | cut -d/ -f2           # 1.26.2

The value from KEY=value lines:

grep '^DB_HOST=' .env | cut -d= -f2-

-f2- matters here. Values that themselves contain = (base64 strings, URLs) keep everything after the first =.

Hostnames from URLs:

cut -d/ -f3 urls.txt

The big limitation: repeated spaces

cut -d' ' treats each space as a delimiter. Output aligned with several spaces, such as ps, df, ls -l and free, produces empty fields and the wrong columns:

df -h | cut -d' ' -f5        # unreliable

Use awk, which splits on runs of whitespace:

df -h | awk '{print $5}'

Or squeeze the spaces first: df -h | tr -s ' ' | cut -d' ' -f5. See awk and tr.

CSV with quoted fields

cut -d, doesn’t understand quotes, so "Smith, John",42 splits in the wrong place. For real CSV, use a CSV-aware tool: csvcut (from csvkit), mlr (Miller), or python3 -c with the csv module.

cut vs awk

Need Tool
Single-character delimiter, simple fields cut
Whitespace-aligned columns awk
Reorder fields (3,1) awk (cut always prints in input order)
Conditions, maths, formatting awk
Character positions cut -c

Note that cut -f3,1 prints field 1 then field 3. It never reorders.

Quick reference

Task Command
Field N, delimiter : cut -d: -fN
Several fields cut -d, -f1,3
Range cut -d, -f2-4
From N to end cut -d= -f2-
Characters cut -c1-10
All except field cut -d, -f2 --complement
Skip lines without delimiter cut -s

Related: wc and sed.

  • Linux
  • Command Line
  • Text Processing