Bash error: Argument list too long
When a glob expands to more files than ARG_MAX, Bash fails with "Argument list too long". Use `find -exec`, xargs, or batched globs.
Error String
bash: /bin/rm: Argument list too long
Tldr
The kernel limits the total bytes of arguments + environment for a process (typically ~2 MB). A glob that expands to tens of thousands of files exceeds it. Use `find ... -delete`, `find ... -exec ... +`, or `xargs` to batch.
Cause
Commands like `rm *.log`, `mv * /backup/`, or `grep pattern *.txt` materialize every match into a single argv. When the directory holds thousands of files, the total argv size exceeds ARG_MAX (`getconf ARG_MAX`).
Repro
# In a dir with 100k log files:
rm *.log # /bin/rm: Argument list too longFix
# find handles batching internally:
find . -maxdepth 1 -name '*.log' -delete
# Or pipe through xargs (one exec per batch):
find . -maxdepth 1 -name '*.log' -print0 | xargs -0 rm
# Or a shell loop (slowest but always works):
for f in *.log; do rm -- "$f"; doneExplanation
The for-loop form works because `*.log` is expanded by the shell into the loop, which only consumes a few entries at a time — argv is never built. It is slower than `find -delete` but never overflows.
Related Shellcheck
SC2035
Faq
Q
Why does the same command work in another directory?
A
The limit depends on how many files the glob matches and how big the environment is, so it appears only past a threshold.
Q
Is xargs safe with unusual filenames?
A
Only with `-0` and a `find -print0` producer; plain `xargs` splits on whitespace and quotes.
Deep Dive
Heading
A kernel limit, not a shell bug
Body
E2BIG is raised by `execve` when the combined size of arguments and environment exceeds the system limit — check it with `getconf ARG_MAX`. A glob such as `rm *.log` in a directory with a hundred thousand files expands before the command runs, so the shell hands the kernel a single enormous argument list. The environment counts towards the same budget, which is why the failure appears in CI (with large exported variables) before it appears locally.
Heading
Batch the work instead
Body
`find . -maxdepth 1 -name "*.log" -print0 | xargs -0 rm --` splits the work into as many `rm` invocations as needed and handles spaces and newlines in filenames safely. `find ... -delete` avoids exec entirely for deletion, and `find ... -exec cmd {} +` batches arguments the same way `xargs` does. For copies and moves, `rsync` streams the file list rather than passing it as arguments. A `while IFS= read -r -d ""` loop is the last resort when each item needs shell logic.
Checklist
Check the ceiling with `getconf ARG_MAX`.
Replace bare globs with `find ... -print0 | xargs -0`.
Use `find -delete` or `-exec cmd {} +` where they apply.
Trim large exported environment variables in CI.