Finding only leaf folders
Posted on November 28, 2005
How can I find only leaf folders in unix? I have a couple of ways I don’t really like. Surely this should just be an option on find. Anyway:
Option 1: Counting Hard Links
find -type d -links 2
Why I don’t like it: It won’t work if there are any hard links (other than . and ..) to any of the folders.
Option 2: Post-processing using awk
find -type d | awk 'NR == 1 {prev = $0}
index($0, prev) != 1 { print prev }
{ prev = $0 }
END { print $prev }'
Why I don’t like it: It’s fugly and long.
Lazyweb, can you help? Or should I just stop being fussy?
UPDATE: Option 1 it is. Because:
- I don’t have any other hard links to those folders, and
- I couldn’t make hard links even if I wanted to (see this comment)
» Filed Under Blogger Posts
Comments
9 Responses to “Finding only leaf folders”
You might get more responses if you didn’t force people to comment with a Blogger ID.
Sorry about that, fixed now.
find -type d -empty
Thanks Jan,
But it seems that only finds empty folders, which by definition would have to be leaves, but it doesn’t find leaf folders containing files.
Ah, now I understand. Well, I think option 1 is the way to go. I believe it’s impossible to create hard links to directories. Here’s a test I did:
# ln source target
ln: `source’: hard link not allowed for directory
Hope that helps!
Jan, I think you are right in that (except in very unusual circumstances) hard links cannot be created for directories. For example at this page we find:
Some versions of Unix have historically allowed root (superuser) to create hard links to directories — but the GNU utilities under Linux won’t allow it
I think you are correct in that the first solution should be adequate. It seems like something that should be specified directly in find tho.
You may or may not find this more long/ugly than your AWK solution:
#!/bin/sh
list_leaves()
{
if subdirs=`ls -d $1*/ 2>/dev/null`; then
for d in $subdirs; do
list_leaves $d
done
else
echo $1
fi
}
list_leaves $1/
Awesome, blogger removed all of my non-breaking spaces during the “preview” step.
#!/bin/sh
list_leaves()
{
if subdirs=`ls -d $1*/ 2>/dev/null`; then
for d in $subdirs; do
list_leaves $d
done
else
echo $1
fi
}
list_leaves $1/
Thanks, but I think I’ll stick to the ‘-links 2′ method.
When compared to the ‘fugly’ awk method, it is a little more elegant in that you can actually tell what it is doing at a glance. However, if anything, it seems it would require more processing.