[lug] "find" question

Tkil tkil at scrye.com
Wed Aug 18 01:16:51 MDT 2004


>>>>> "Daniel" == Daniel Webb <lists at danielwebb.us> writes:

Daniel> Aha!  I'm embarassed, but I didn't even know about the -xtype option.
Daniel> Here's the command I wanted all along:

Daniel> find . -follow \( -type f -a \! -xtype l \)

Just btw, I think that you can drop the parens and the "-a"; "and" is
implied between two conjoined clauses, and since there's nothing to
nest, you don't need the parens.  So it should be the same as:

   find . -follow -type f \! -xtype l

In fact, bash isn't nearly as twitchy as csh is about the naked bang,
either:

   find . -follow -type f ! -xtype l

One thing I did notice, though, is that this can return the same file
multiple times (if it gets there through different paths / links).
Using the same simple hierarchy I set up in my last message, I got:

| $ find . -follow -type f ! -xtype l
| ./a/foo
| ./b/bar
| ./b/baz
| ./c/bar
| ./c/baz

(This does successfully ignore ./a/lbar, which is a symlink to a file)

Not sure if there is a cheap way to get rid of duplicates.  'find' has
to keep track of uniqueness internally, typically with dev/inode
tuples, but I couldn't find a way to make it do it for me, so I
resorted to this gross hack:

| $ find . -follow -type f ! -xtype l \
|   -exec readlink --canonicalize '{}' \; | \
|   sort | uniq | sed -e "s@^$PWD at .@"
| ./a/foo
| ./b/bar
| ./b/baz

Oooh, I forgot about "-i" to 'ls'.  If we know all these files are on
the same filesystem, we can use that to uniquify the results,
hopefully more cheaply than by canonicalizing symlink paths... but I
can't think of a short way to compare only the first field of the
output.  Huh.  So I haul out the swiss army chainsaw again:

| $ find . -follow -type f ! -xtype l -print0 | \
|     xargs -0 ls -1i --quoting-style=shell | \
|     perl -lne '($inode,$rest) = split " ", $_, 2;
|                print $rest unless $seen{$inode}++'
| ./a/foo
| './b/bad name'
| ./b/bar
| ./b/baz

(I added "b/bad name", yes with a space in it, to test the quoting /
wordsep capabilities of my pipeline... seems to have worked.)

Daniel> Rephrased, what I want to accomplish is:

Daniel>    List all non-link files in a directory tree.  Directory
Daniel>    symbolic links should be followed.

Daniel> -xtype solves the problem I was having when only using -type.
Daniel> GNU tools are the best!

Yeah.  The non-standardness can occasionally be a pain, but GNU/Linux
is rapidly becoming its own standard.  So.

Happy hacking,
t.



More information about the LUG mailing list