Fixing "Argument list too long" — When rm * and Similar Commands Fail
What This Article Covers
- Why
rm *andcp * dest/fail with "Argument list too long" - How to process large numbers of files safely using
find + xargsandfind -delete - How to handle filenames with spaces or special characters
Quick fix
# Replacement for rm * — safest approach find . -maxdepth 1 -name "*.log" -type f -delete # Or via xargs find . -maxdepth 1 -name "*.log" -print0 | xargs -0 rm
Why Does "Argument list too long" Happen?
When you run rm *, the shell (not rm) expands the wildcard first. With tens of thousands of files, the resulting argument list exceeds the kernel limit ARG_MAX, and the kernel returns an E2BIG error.
$ rm *.log -bash: /bin/rm: Argument list too long
Check your system's ARG_MAX:
$ getconf ARG_MAX 2097152
2097152
The typical value on Linux is 2 MB (2,097,152 bytes). Once the total length of all expanded arguments exceeds this, the command fails.
This error affects any command that uses wildcards: ls *.log, cp *.log dest/, cat *.txt, chmod 644 *.php, and so on.
find processes files one at a time and never builds a full argument list for exec(), which is why it bypasses this limit entirely.
Fix with find -delete
For deletion, find -delete is the simplest and safest option — no xargs required.
find . -maxdepth 1 -name "*.log" -type f -delete
-maxdepth 1: current directory only (equivalent scope torm *)-type f: files only (prevents accidental directory deletion)-delete: delete each match
To include subdirectories, remove -maxdepth:
find /path/to/dir -name "*.log" -type f -delete
Before deleting, verify what will be removed:
# Preview matches and count find . -maxdepth 1 -name "*.log" -type f find . -maxdepth 1 -name "*.log" -type f | wc -l
Fix with find + xargs
A general-purpose pattern that works with any command, not just rm.
Basic pattern
find . -maxdepth 1 -name "*.log" | xargs rm
xargs automatically batches arguments to stay within ARG_MAX.
Filenames with spaces or special characters
Default xargs splits on whitespace, which breaks filenames containing spaces. Use -print0 with xargs -0 (NUL-delimited) for full safety:
find . -maxdepth 1 -name "*.log" -print0 | xargs -0 rm
Using -print0 | xargs -0 as the default is the safest habit.
Parallel execution for speed
find . -name "*.log" -print0 | xargs -0 -P4 rm
-P4 runs 4 processes in parallel. Useful when deleting a very large number of files.
Fix for cp / mv
The same E2BIG error appears with cp * dest/ and mv * dest/.
# cp
find . -maxdepth 1 -name "*.log" -print0 | xargs -0 -I{} cp {} /dest/
# mv
find . -maxdepth 1 -name "*.log" -print0 | xargs -0 -I{} mv {} /dest/-I{} substitutes each path into {}.
You can also use -exec:
find . -maxdepth 1 -name "*.log" -exec cp {} /dest/ \;-exec spawns one process per file, so xargs is faster for large file counts.
Fix with a Shell Loop
A simple alternative when find is unavailable, or when you need to review each file before acting.
for f in *.log; do
rm "$f"
doneThe shell invokes rm once per file, so ARG_MAX is never reached.
Always quote "$f". Without the quotes, filenames containing spaces will cause the loop to break.
Summary
| Approach | Example | Best for |
|---|---|---|
find -delete |
find . -name "*.log" -type f -delete |
Deletion only (simplest) |
find | xargs rm |
find . -name "*.log" | xargs rm |
Standard deletion |
-print0 | xargs -0 |
find . -name "*.log" -print0 | xargs -0 rm |
Special-char filenames |
| Shell loop | for f in *.log; do rm "$f"; done |
Step-by-step review |
-exec |
find . -name "*.log" -exec cp {} /dest/ \; |
Non-delete operations |
Decision flow
- Deleting files →
find -delete - Copying or moving →
find ... -print0 | xargs -0 command - Review each file as you go → shell loop