/bin/rm annoying limitation: Argument list too long
I recently had to write a small shell script to clean up some temporary files that were left over in the homes of all the users in one system. No problem, all very simple, but in the process of running the script, I was hit by one very annoying limitation in the /bin/rm command that was failing if there were too many files to delete. Now since I have seen this previously and solved it very easy this was not a real problem, but I thought it might be useful to other readers of the site that are having similar problems.
Now in the loop of the script I have used the simple command to delete the files in cause like this:
rm -f /home/$u/tmp/*.wrk
This command was failing in case there were too many files in the respective folder, with the following error:
-bash: /bin/rm: Argument list too long
How many files were in there?
ls -1 | wc -l
2855
Actually this is not a limitation of the rm command, but a kernel limitation on the size of the parameters of the command. Since I was performing shell globbing (selecting all the files with extension .wrk), this meant that the size of the command line arguments became bigger with the number of the files involved. For who cares this is defined by:
egrep ARG_MAX /usr/include/linux/limits.h
#define ARG_MAX 131072 /* # bytes of args + environ for exec() */
The possible solutions are to either run the rm command inside a loop and delete each individual result, or to use find with the xargs parameter to pass the delete command. I prefer the find solution so I had changed the rm line inside the script to:
find /home/$u/tmp/ -name '*.wrk' -print0 | xargs -0 rm
this does the trick and solves the problem. One final touch was to not receive warnings if there were no actual files to delete, like:
rm: too few arguments
Try
rm --help' for more information.
For this I have added the -f parameter to rm (-f, –force = ignore nonexistent files, never prompt). Since this was running in a shell script from cron the prompt was not needed also so no problem here. The final line I used to replace the rm one was:
find /home/$u/tmp/ -name '*.wrk' -print0 | xargs -0 rm -f