2

I am trying to remove large amount of mails (mostly mail delivery failed) from my server using

 rm -rf /home/*/mail/new/*

And I am getting -bash: /usr/bin/rm: Argument list too long

I tried using find

find /home/*/mail/new/ -mindepth 1 -delete

But after 20 minutes it looks like it's not doing anything.

How do I use for loop to delete everything (directories, files, dotfiles) within /home/*/mail/new/

Something like this

for f in /home/*/mail/new/*.*~; do
        # if it is a file, delete it
    if [  -f $f ]
    then
        rm "$f"
    fi
done

Please help me rewrite this command to delete files AND folders and everything within /home/*/mail/new/

EDIT: My question is unique because it's about doing that in FOR loop.

sourcejedi
  • 48,311
  • 17
  • 143
  • 296
Luka
  • 2,067
  • 3
  • 10
  • 14
  • The `find` command looks fine. If you want to show what it's, doing use `-print -delete` – jordanm Feb 28 '17 at 19:47
  • I think `for` has better performance than find. – Luka Feb 28 '17 at 19:50
  • 1
    It doesn't. Shell loops are *slow*. Nothing will be slower than the loop and `find` should be orders of magnitude faster. – terdon Feb 28 '17 at 19:56
  • see also [Efficiently delete large directory containing thousands of files](http://unix.stackexchange.com/q/37329) – don_crissti Feb 28 '17 at 20:03
  • not duplicate. That is not what question is about, i asked how to remove all files, folders and dotfiles using for loop, and there is no answer on internet for that. – Luka Feb 28 '17 at 20:05
  • you could start splitting the loops up -- `for d in /home/*; do rm -rf "/home/$d/mail/....` and even sections of filenames from there. – Jeff Schaller Feb 28 '17 at 20:55

1 Answers1

4

The problem is that /home/*/mail/new/* expands to too many file names. The simplest solution is to delete the directory instead:

rm -rf /home/*/mail/new/

Alternatively, use your find command. It should work, it will just be slower.

Or, if you need the new directories use a loop to find them, delete and recreate them:

for d in /home/*/mail/new/; do
    rm -rf "$d" && mkdir "$d"
done

The loop you were trying to write (but don't use this, it is very slow and inefficient) is something like:

for f in /home/*/mail/new/* /home/*/mail/new/.*; do
    rm -rf "$f"
done

No need to test for files if you want to delete everything, just use rm -rf and both directories and files can be deleted by the same command. It will complain about not being ab;e to delete . and .. but you can ignore that. Or, if you want to be super clean and avoid the errors, you can do this in bash:

shopt -s dotglob
for f in /home/*/mail/new/*; do
        rm -rf "$f"
done
terdon
  • 234,489
  • 66
  • 447
  • 667
  • Then my only solution is to delete whole `new` directory and recreate it. – Luka Feb 28 '17 at 19:59
  • 1
    @Luka no, you can use your `find` command and wait a bit. But yes, deleting and recreating is by far the easiest and fastest way. I also added the loop you were asking for but that will be far slower than anything else. – terdon Feb 28 '17 at 20:01
  • I added `nice -n -20` to find command, and its a lot faster – Luka Feb 28 '17 at 20:16
  • 1
    @Luka OK, that suggests you have a pretty busy machine and other things were taking precedence. The main take home message here is that *shell loops are slow and inefficient*, pretty much *anything* will be faster than a shell loop. – terdon Feb 28 '17 at 22:02