Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Bash & Python Automation By James Joyner IV · · 8 min read

Bash & Python Error Guide: 'Argument list too long' (E2BIG)

Fix bash 'Argument list too long' (E2BIG): the ARG_MAX limit from wildcards expanding to thousands of files, and how xargs, find -exec, and globbing solve it.

  • #automation
  • #troubleshooting
  • #errors
  • #bash

Overview

Argument list too long is the kernel returning E2BIG when the total size of a command’s arguments plus its environment exceeds ARG_MAX. When you run rm *.log in a directory with hundreds of thousands of files, the shell expands *.log to the full list of filenames before rm ever starts, and the resulting command line is too big to pass to execve(). The limit is on the combined bytes of all arguments and the environment, not on the number of files per se — long paths blow the budget faster than short ones.

The error appears differently depending on who hits the limit:

bash: /bin/rm: Argument list too long
-bash: /usr/bin/grep: Argument list too long

It occurs at exec time, the instant the shell tries to hand the expanded command line to the kernel. Crucially, no part of the command runsrm *.log deletes nothing when it fails this way. The fix is never “raise the limit” (it usually cannot be raised meaningfully); it is to stop building one giant argument list and instead stream the items in batches.

Symptoms

  • A command with a wildcard or large argument list fails immediately with Argument list too long.
  • The command performs no work at all (the failure is at exec, before the program starts).
  • It fails only in directories that have grown large; the same command works elsewhere.
  • Sometimes it is a wrapped form: xargs: ...: Argument list too long if even a single argument is enormous.
ls /var/log/app/ | wc -l
482190
rm /var/log/app/*.log
bash: /usr/bin/rm: Argument list too long

Common Root Causes

1. A wildcard expands to too many files

The shell glob *.log becomes one argument per file; with hundreds of thousands of files the line exceeds ARG_MAX.

echo /var/log/app/*.log | wc -c
getconf ARG_MAX
14237891
2097152

The expanded line (14 MB) dwarfs ARG_MAX (2 MB). Stream instead of expanding (see find/xargs below).

2. Passing a big file list to cp, mv, grep, cat, etc.

Any command receiving an expanded glob hits the same wall — grep pattern *.txt, cp *.dat /dest/, cat *.json.

grep "ERROR" /var/log/app/*.log
-bash: /usr/bin/grep: Argument list too long

Use find ... -exec or pipe filenames through xargs.

3. Long absolute paths inflating the byte count

Even a modest file count fails if each path is very long (deeply nested directories), because ARG_MAX is a byte limit, not a count limit.

find /data/tenants/acme/prod/2026/06/exports -maxdepth 1 -type f | head -1 | wc -c
72

At ~72 bytes per path, fewer files are needed to exceed the limit than with short names.

4. A bloated environment eating into the budget

ARG_MAX covers arguments and environment variables. A huge env (e.g., a multi-megabyte variable) shrinks the room left for arguments, so commands fail at a smaller file count than expected.

env | wc -c
1980442

A ~1.9 MB environment leaves almost nothing under a 2 MB ARG_MAX. Trim oversized exported variables.

5. xargs with a single oversized item or -L/no batching misuse

xargs normally batches automatically, but xargs -I{} runs one invocation per line (slow), and a single line longer than the limit still fails.

find . -name '*.tmp' -print0 | xargs -0 -I{} rm {}

This runs rm once per file (correct but slow). Drop -I{} to let xargs batch:

find . -name '*.tmp' -print0 | xargs -0 rm

6. Building a command line inside a script from a growing array

A script that accumulates filenames into a variable and passes $FILES unquoted to a command hits the limit as the set grows.

FILES=$(find /data -name '*.bak')
rm $FILES        # word-splits into a huge arg list
bash: /usr/bin/rm: Argument list too long

Pipe through xargs instead of expanding a variable.

Diagnostic Workflow

Step 1: Confirm it is the argument size, not a syntax error

<command> 2>&1 | grep -i "Argument list too long"

The exact message confirms E2BIG; the command did nothing.

Step 2: Measure the expansion against ARG_MAX

echo <pattern> | wc -c
getconf ARG_MAX
ls -1 <dir> | wc -l

If the expanded byte count approaches or exceeds ARG_MAX, that is the cause.

Step 3: Replace the glob with find + -print0 and xargs -0

find <dir> -maxdepth 1 -name '*.log' -print0 | xargs -0 rm

-print0/-0 use NUL separators so spaces/newlines in names are safe; xargs batches under the limit automatically.

Step 4: Or use find -exec ... + for the same batching

find <dir> -maxdepth 1 -name '*.log' -exec rm {} +

The trailing + (not \;) packs as many files as fit per rm invocation.

Step 5: For greps/copies, stream filenames

find <dir> -name '*.txt' -print0 | xargs -0 grep "ERROR"
find <dir> -name '*.dat' -print0 | xargs -0 -I{} cp {} /dest/   # or cp --target-directory

Example Root Cause Analysis

A log-rotation cleanup script that ran fine for a year suddenly fails:

/opt/scripts/cleanup.sh: line 6: /bin/rm: Argument list too long

The script’s line 6 is:

rm -f /var/spool/mqueue/*.tmp

A queue backlog let the temp files accumulate:

ls -1 /var/spool/mqueue/*.tmp 2>/dev/null | wc -l
echo /var/spool/mqueue/*.tmp | wc -c
getconf ARG_MAX
911403
58329792
2097152

The glob expands to ~58 MB of filenames — far beyond the 2 MB ARG_MAX — so rm never starts and not a single file is removed, which is why the backlog kept growing.

Fix: stream the deletions with find so they are batched under the limit:

find /var/spool/mqueue -maxdepth 1 -name '*.tmp' -type f -delete
# or, if -delete is unavailable:
find /var/spool/mqueue -maxdepth 1 -name '*.tmp' -type f -print0 | xargs -0 rm -f

The cleanup now drains the backlog in batched unlink calls, and the script completes.

Prevention Best Practices

  • Never feed a raw wildcard to commands in directories that can grow unbounded; use find ... -exec {} + or find ... -print0 | xargs -0, which batch automatically under ARG_MAX.
  • Prefer find -delete for bulk deletions when available — it calls unlink directly and avoids building any argument list at all.
  • Always use -print0/xargs -0 so filenames containing spaces or newlines are handled safely, not just to dodge the size limit.
  • Avoid accumulating filenames into a shell variable and expanding it unquoted; stream from find instead.
  • Keep the exported environment lean in scripts — oversized variables steal from the same ARG_MAX budget the arguments use.
  • For diagnosing batch-job failures in scheduled automation, the free incident assistant can flag an E2BIG from job output. More patterns in the Bash & Python automation guides.

Quick Command Reference

# Inspect the limit and the expansion
getconf ARG_MAX
echo <dir>/*.log | wc -c
ls -1 <dir> | wc -l

# Delete safely in batches
find <dir> -maxdepth 1 -name '*.log' -type f -delete
find <dir> -maxdepth 1 -name '*.log' -print0 | xargs -0 rm -f

# -exec with + (batched)
find <dir> -name '*.log' -exec rm {} +

# Grep / copy across many files
find <dir> -name '*.txt' -print0 | xargs -0 grep "ERROR"
find <dir> -name '*.dat' -print0 | xargs -0 cp -t /dest/

# Check environment bloat
env | wc -c

Conclusion

Argument list too long (E2BIG) is the kernel rejecting a command line whose arguments plus environment exceed ARG_MAX. The recurring causes:

  1. A wildcard expanding to too many files before the command runs.
  2. Passing a huge expanded glob to rm/cp/grep/cat.
  3. Long absolute paths inflating the byte count past the limit.
  4. A bloated environment shrinking the room left for arguments.
  5. xargs -I{} misuse defeating automatic batching.
  6. Expanding a large filename variable unquoted in a script.

The fix is to stop building one giant argument list: stream items with find -print0 | xargs -0 or find -exec {} + (or find -delete for removals), which batch under ARG_MAX automatically. Remember the command did nothing when it failed this way — re-run the batched form to actually do the work.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.