/bin/rm: Argument list too long
This post was written on January 5, 2007 at, or around 10:47 pm by Drew. This post is composed of 574 words from the English language and currently has 12 comments to its name. Additionally, this article is tagged under Career, File Systems, Management, Sys Admin, The Notebook, Tips, UNIX/Linux and you can trackback to this article using this link. This post was last updated on Apr 4, 2008. Enough talk, carry on.
Currently, I work as a Datacenter Technician at The Planet. I had a customer ask me how to, one time, delete all the mail in his /home/[account-name]/mail/cur directory.
So, first off, I wanted him to just take a look at that directory, get to know it (figuratively speaking). So I had him run the du command on it; wow, you wouldn’t imaging how much mail was in there!
The actual command I had him run was:
BASH
cd /home/[account-name]/mail/cur
du -h ./
The output was 1.3GB. Yes, that’s right, he had 1.3GB of mail files. Some people are unaware of what exactly the difference is between the /new directory and the /cur. The difference is simply that the /cur directory is full of email messages that the user has already viewed somehow, whether by webmail, Outlook, Thunderbird, etc, they have viewed it, and the mail is now officially not exactly new. The /new directory is a directory that has mail that has not yet been opened by the user yet.
So, the customer asked me a simple question, “How do I go about just deleting this data?”. From a user’s point of view, the command would be:
BASH
cd /home/[account-name]/mail/cur
rm -r ./*
Then the customer would have received the error: /bin/rm: Argument list too long. I have found a workaround though. I have asked a few people around what they use the find command for. All of there answers where pretty much the same, “They help you find files”. That’s all they could really tell me what find does. This isn’t all true. find can help us defeat the /bin/rm: Argument list too long error. So, I had the customer run the following:
BASH
cd /home/[account-name]/mail/cur
find . -name '11*' -exec rm "{}" \;
It worked for him, and it can work for you. Let me dissect this command real quick for you, so that you aren’t completely lost. find is the actual command, followed by a period; this means you are going to be searching the current directory (at this time /home/[account-name]/mail/cur). Next you supply the -name switch to tell the find command that you want the pattern (coming next) to match the name of the file. You then give it a search pattern, and in this case all his files started with eleven (11) and everything after that was different, so the pattern would be 11*; make sure the search pattern is in single quotes. Next you supply the -exec command, which will execute any Linux command you want (as long as it is installed on your system). In this case we used the rm command. The quoted curly braces tell it to run rm on each file that matches the pattern supplied. That’s it. Simple command turns to be a very helpful utility.
Hope this helps someone in the future, as I had to figure it out on my own.
Discussion always soothes thy heart.
Just commenting that I just removed 2.6 gigs from my own personal cur/ directory using the following command:
for f in *; do rm -rf $f; done
Just as an alternative to what you’ve posted.
As I would agree with you, I would have to admit that I would not do it this way.
For all you new Linux people and non-programmers (especially Shell Programmers), this is a one-line BASH script rolled into one line - notice the semicolons. For loop comes first, followed b the do command (for everytime this is true, do this), and then exit (done).
I personally would not use this as find is far more powerful than this for loop, but I will admit to you that I use this type of style (for…do) method for cleaning out old/large log files. Thanks for sharing Erin.
Good stuff :)
Me being me, how do I do this to remove a specific file name like upgrade.txt.1,.2,.3… From a directory recursively? Only files that contain upgrade.txt. :-)
Joe,
In order to do what you are wanting, you would simply change the search expression like so:
find . -name 'upgrade.txt.*' -exec rm "{}" ;
Also note that in your reply, you stated upgrade.txt.1, so that’s why I said make sure it says upgrade.txt.*
If you just want it to find anything with upgrade.txt, you would need to issue the following:
find . -name 'upgrade.txt*' -exec rm "{}" ;
Hope this helps!
Your solution is very slow and inefficient, as it’ll call rm once for every single file. What you want is:
find . -name ‘11*’ | xargs rm
@ Craig: Don’t know about that. I mean, I hope you aren’t another one of those “this took 2.345547 seconds longer to run than this other one” kind of guy. The original error I found was my fix and it is very efficient and fast :)
Regards,
Drew
Erin’s method caused a segmentation fault when processing a huge number of files in one particular directory.
Drew’s find example worked fine in that case.
Thanks, this was helpful.
Thanks Drew, I just deleted 817 million CCTV images with this, saved my bacon. It did take a few days!
Thanks Drew, I just deleted 817 million CCTV images with this, saved my bacon. It did take a few days!
Wow! That’s awesome! Glad I could help :)
Regards,
Drew
That is AWESOME! Thanks so much - I’ve been looking for an easy way to get around this ‘Argument List Too Long’ error.
This worked perfectly.