From: James on
In unix, how to do efficiently
find and delete empty directories recursively

If no regular files (or symlink) present, it is considered as empty.
Directories with emtpy subdirectories are considered as empty also.

TIA
JL
From: pk on
James wrote:

> In unix, how to do efficiently
> find and delete empty directories recursively
>
> If no regular files (or symlink) present, it is considered as empty.
> Directories with emtpy subdirectories are considered as empty also.

The real problem here is to determine whether a directory is empty, which is
generally not straightforward and subject to race conditions.

Your second requirement can be accomplished by traversing the directories in
a depth-first fashion, so when all the subdirectories have been determined
to be empty and removed, the parent directory will be empty and removed as
well.

Once you have a good method to determine if a directory is empty (that is,
good enough for your case), you can do

find /basedir -depth -type d -exec isempty.sh {} \; -exec rmdir {} \;

(or you can even do the removal in the isempty.sh script if you want)

With bash, assuming you don't care about race conditions, you can use this
code to check for emptiness (this could be a sample isempty.sh):

----------------------------------------
#!/bin/bash

shopt -s nullglob
shopt -s dotglob

directory=$1
empty=1

for i in "$directory"/*; do
empty=0
break
done

if [ $empty -eq 1 ]; then
# directory is empty
return 0
fi

return 1
----------------------------------------

or as I said, you can run "rmdir "$directory" directly in the script.
From: Stachu 'Dozzie' K. on
On 2010-05-13, pk <pk(a)pk.invalid> wrote:
> James wrote:
>
>> In unix, how to do efficiently
>> find and delete empty directories recursively
>>
>> If no regular files (or symlink) present, it is considered as empty.
>> Directories with emtpy subdirectories are considered as empty also.
>
> The real problem here is to determine whether a directory is empty, which is
> generally not straightforward and subject to race conditions.

What? O_o
I've always thought that rmdir() is atomic syscall.

find . -type d | sort -r | xargs rmdir

--
Secunia non olet.
Stanislaw Klekot
From: pk on
Stachu 'Dozzie' K. wrote:

> On 2010-05-13, pk <pk(a)pk.invalid> wrote:
>> James wrote:
>>
>>> In unix, how to do efficiently
>>> find and delete empty directories recursively
>>>
>>> If no regular files (or symlink) present, it is considered as empty.
>>> Directories with emtpy subdirectories are considered as empty also.
>>
>> The real problem here is to determine whether a directory is empty, which
>> is generally not straightforward and subject to race conditions.
>
> What? O_o
> I've always thought that rmdir() is atomic syscall.
>
> find . -type d | sort -r | xargs rmdir

Well, if you do it like that you rely on rmdir failing, which does not have
race conditions. While it may be a solution, I personally don't like having
the screen cluttered with pointless error messages; at the same time, I
don't want to redirect stderr to /dev/null because then I could miss real
errors.

So I check for emptiness first, and then delete; this is a potential race.
In practice, if you know that the directory tree isn't being modified, the
race condition problem can be ingored.
From: pk on
pk wrote:

> Stachu 'Dozzie' K. wrote:
>
>> On 2010-05-13, pk <pk(a)pk.invalid> wrote:
>>> James wrote:
>>>
>>>> In unix, how to do efficiently
>>>> find and delete empty directories recursively
>>>>
>>>> If no regular files (or symlink) present, it is considered as empty.
>>>> Directories with emtpy subdirectories are considered as empty also.
>>>
>>> The real problem here is to determine whether a directory is empty,
>>> which is generally not straightforward and subject to race conditions.
>>
>> What? O_o
>> I've always thought that rmdir() is atomic syscall.
>>
>> find . -type d | sort -r | xargs rmdir
>
> Well, if you do it like that you rely on rmdir failing, which does not
> have race conditions. While it may be a solution, I personally don't like
> having the screen cluttered with pointless error messages; at the same
> time, I don't want to redirect stderr to /dev/null because then I could
> miss real errors.
>
> So I check for emptiness first, and then delete; this is a potential race.
> In practice, if you know that the directory tree isn't being modified, the
> race condition problem can be ingored.

And, it's probably worth adding, the straight rmdir solution may be adequate
for this specific problem, where all we want is to remove the directory; if
the emptiness test is being used for something else, then we can't use
rmdir.