Skip to content
ohsudo, Home
Linux

"Argument list too long": delete or move thousands of files on Linux

Fix "Argument list too long" for rm, mv, cp or grep with a wildcard: why the kernel refuses, and how find -delete, find -exec + and xargs handle any number of files.

Beginner3 min readApplies to Bash · Ubuntu · Debian · RHEL / Rocky / AlmaLinux · GNU findutils

by OhSudo ·

A folder filled up with files over months — temp files, cache entries, old logs — and the obvious cleanup fails:

$ rm *.tmp
-bash: /usr/bin/rm: Argument list too long

The same happens with mv, cp, ls, grep, tar — any program you give a big wildcard. The program never even starts. Bash expands *.tmp into the full list of file names before running rm, and the kernel limits how much text a new program may receive as arguments: getconf ARG_MAX shows it, usually 2 MiB on Linux. Tens of thousands of file names are more than that.

So the fix isn’t a different rm option. It’s not putting all the names on one command line.

TL;DR

Terminal window
find . -name "*.tmp" -delete

Or, to run any command on them in safe batches:

Terminal window
find . -name "*.tmp" -print0 | xargs -0 rm

1. See how big the list is

Terminal window
ls | wc -l
echo *.tmp | wc -c
60001
2220000

echo works where rm doesn’t: it’s built into Bash, so the list never goes through the kernel. Here the names alone take about 2.2 MB — over the 2 MiB limit.

2. Delete with find

find walks the folder itself and deletes each file as it goes. There’s no list at all, so there’s no limit:

Terminal window
find . -name "*.tmp" -delete

Check first what would be deleted — run it without -delete:

Terminal window
find . -name "*.tmp" | head -3

Useful extra conditions: -maxdepth 1 (don’t go into subfolders), -type f (only files), -mtime +7 (older than 7 days).

3. Any other command: find -exec + or xargs

For mv, cp, chmod, grep or anything else, let find (or xargs) split the list into batches that fit:

Terminal window
find . -name "*.tmp" -exec rm {} +

The + at the end makes find pass as many files as fit to each rm call, then start another one. (With \; instead, it would start one rm per file — correct, but much slower.)

xargs does the same with any list on its input. Use -print0 and -0, so file names with spaces or newlines can’t break it:

Terminal window
find . -name "*.tmp" -print0 | xargs -0 rm

Moving files needs the destination before the list, so put it first with -t:

Terminal window
find . -name "*.tmp" -print0 | xargs -0 mv -t /var/archive/

4. Other ways

  • The whole folder: if everything in it can go, rm -r /var/spool/app (one argument) works instead of rm /var/spool/app/*. Recreate the folder if the app needs it.
  • Bash’s printf is a builtin, like echo, so it can feed the list to xargs without hitting the limit: printf '%s\0' *.tmp | xargs -0 rm.
  • A loop works too, but starts one program per file — slow with 100,000 files: for f in *.tmp; do rm -- "$f"; done.
  • tar reads the list from its input: find . -name "*.log" -print0 | tar --null -czf logs.tar.gz -T -.

Note

Fix the cause, too. A folder with this many files usually means a cleanup that never runs: a missing cron job (see Cron job not running) or an app that never deletes its temp files. A daily find /var/spool/app -name "*.tmp" -mtime +1 -delete keeps it from coming back.

Shell, we have a problem!

Similar, but different: No space left on device with plenty of free space can mean the filesystem ran out of inodes — millions of tiny files; see No space left on device. Too many open files is about files a program has open, not their number in a folder — see Too many open files. For more recipes, see the find, grep, sed and awk Cheat Sheet. To learn find step by step, try that lesson.

$ ./practice.sh

Practice this in the terminal

Open the Terminal Playground with this article’s scenario loaded. It is safe and runs in your browser.

Open the terminal →

Found this useful? Share it.

Found a mistake? Let us know at contact@ohsudo.com.

Tools

Try it yourself

Articles

Related articles