Skip to content
🎉 Launch sale:50% off everything over $22 — automatically applied at checkout· ends Aug 2Shop the sale →
DevOps AI ToolKit
Newsletter
All guides
AI for Automation By James Joyner IV · · 8 min read Last reviewed Jul 2026

xargs Error: 'argument line too long' — Cause, Fix, and Troubleshooting Guide

Quick answer

Fix 'xargs: argument line too long' and 'Argument list too long' — understand ARG_MAX, batch with xargs -n/-s, and use find -print0 | xargs -0 safely.

  • #automation
  • #troubleshooting
  • #xargs
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

xargs: argument line too long means a single command xargs tried to build exceeded the kernel’s limit on the size of one command line plus its environment. There is a hard ceiling — ARG_MAX — on how many bytes of arguments and environment execve() will accept, and xargs refused to run a command that would blow past it:

$ find /opt/jobs/exports -name '*.json' | xargs -L1000 rm
xargs: argument line too long

You hit the same underlying limit — from the other direction — when you skip xargs entirely and let the shell expand a glob directly into a command. The kernel rejects the execve() and the tool, not the shell, reports it:

$ rm /opt/jobs/exports/*.json
bash: /bin/rm: Argument list too long

Both messages are the same problem: too many bytes of arguments in one execve() call. ARG_MAX is typically ~2 MB on Linux, but it is shared with the environment, and per-argument overhead (a pointer plus a trailing NUL for each string) counts too — so a directory with tens or hundreds of thousands of long paths overflows it.

Symptoms

  • xargs: argument line too long when forcing large batches with -L or a big -n.
  • bash: /bin/rm: Argument list too long (or cp, mv, grep, ls) when a glob expands directly onto the command line.
  • The command works in a small test directory but fails once the file count grows.
  • It fails on production data (hundreds of thousands of files) but passes in staging (a few hundred).
ls /opt/jobs/exports/*.json | wc -l
248113

Common Root Causes

1. A glob expands too many arguments onto one command line

rm *.json, cp * dest/, or grep pattern * in a huge directory hands the whole expanded list to a single execve(), which overflows ARG_MAX.

2. xargs was told not to batch

xargs batches automatically by default, but -L, a large -n, or a large -s forces bigger command lines than the kernel allows. Overriding the default defeats the very protection xargs provides.

3. Very long individual paths

Deeply nested or long filenames mean even a modest file count exceeds the byte limit, because it is total bytes — not file count — that matters.

4. A bloated environment eating into ARG_MAX

ARG_MAX is shared between arguments and the environment. A large environment (many exported variables, huge PATH) leaves less room for arguments, so the limit is hit sooner.

How to Diagnose

Find the effective limit and how much room the environment leaves. xargs --show-limits reports exactly what it will honor:

xargs --show-limits < /dev/null
Your environment variables take up 2841 bytes
POSIX upper limit on argument length (this system): 2092264
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2089423
Size of command buffer we are actually using: 131072

The kernel ceiling and how much the environment already consumes are both listed. Cross-check the raw kernel value:

getconf ARG_MAX
2097152

Estimate whether your file list overflows it — total bytes, not count:

find /opt/jobs/exports -name '*.json' -printf '%p\n' | wc -c
9724180

9.7 MB of path bytes against a ~2 MB limit means a single execve() cannot hold the list — it must be batched. Confirm the glob path is the failing one:

# This will fail; count first instead of running it
echo /opt/jobs/exports/*.json | wc -c
9724180

Fixes

Let xargs batch automatically (do not override it)

The simplest fix is to stop forcing large batches. Plain xargs splits the input into as many execve() calls as needed to stay under the limit:

find /opt/jobs/exports -name '*.json' | xargs rm

If you must cap batch size, use a modest -n (arguments per command) or -s (bytes per command) rather than a huge one:

# 500 files per rm invocation
find /opt/jobs/exports -name '*.json' | xargs -n 500 rm
# Or cap by bytes, well under ARG_MAX
find /opt/jobs/exports -name '*.json' | xargs -s 100000 rm

Use find -exec … + which batches natively

find with -exec cmd {} + builds command lines the same way xargs does, respecting ARG_MAX, and needs no pipe:

find /opt/jobs/exports -name '*.json' -exec rm {} +

The trailing + (not \;) is what enables batching; \; would run one process per file — safe but slow.

Handle spaces and newlines safely with -print0 | xargs -0

Filenames with spaces, tabs, or newlines break whitespace-delimited xargs. Use NUL-delimited output and -0 so each path is unambiguous:

find /opt/jobs/exports -name '*.json' -print0 | xargs -0 rm

This is the robust default for any automation touching untrusted filenames — it also sidesteps the “argument line too long” case because xargs still batches, and it never splits a name on whitespace.

Replace direct globs with a batched form

Rewrite rm *.json style commands that overflow the shell:

# Instead of: rm /opt/jobs/exports/*.json
find /opt/jobs/exports -maxdepth 1 -name '*.json' -print0 | xargs -0 rm

What to Watch Out For

  • It is total bytes, not file count. A few thousand very long paths can overflow ARG_MAX while a hundred thousand short ones do not. Estimate with wc -c on the path list, not wc -l.
  • ARG_MAX is shared with the environment. A bloated environment (CI runners often export a lot) shrinks the room for arguments. xargs --show-limits shows how many bytes your environment already consumes.
  • Do not “fix” it by forcing a bigger -s or -n. That reintroduces the overflow. Default xargs and find -exec + already pick safe batch sizes — let them.
  • Whitespace in filenames silently breaks plain xargs. A path with a space becomes two arguments; a newline can even cause the wrong file to be deleted. Always pair find -print0 with xargs -0 for anything destructive.
  • \; versus + matters. find -exec rm {} \; runs one process per file (correct but slow); -exec rm {} + batches. Use + for performance, \; only when the command genuinely takes exactly one argument.
  • Empty input runs the command anyway with GNU xargs unless you pass -r (--no-run-if-empty). Add -r in scripts so an empty list does not run rm with no arguments.
Free download · 368-page PDF

Fixed it? Get 500 Automation & DevOps AI prompts — free

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.

Did this fix your issue?

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

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.