开发者

GNU find: Search in current directory first

how can I tell find to look in the current folder first and then continue search in subfolders开发者_运维技巧? I have the following:

$ find . -iname '.note'
folder/1/.note
folder/2/.note
folder/3/.note
folder/.note

What I want is this:

$ find . -iname '.note'
folder/.note
folder/1/.note
folder/2/.note
folder/3/.note

Any ideas?


find's algorithm is as follows:

  • For each path given on the command line, let the current entry be that path, then:
    1. Match the current entry against the expression.
    2. If the current entry is a directory, then perform steps 1 and 2 for every entry in that directory, in an unspecified order.

With the -depth primary, steps 1 and 2 are executed in the opposite order.

What you're asking find to do is to consider files before directories in step 2. But find has no option to do that.

In your example, all names of matching files come before names of subdirectories in the same directory, so find . -iname '.note' | sort would work. But that obviously doesn't generalize well.

One way to process non-directories before directories is to run a find command to iterate over directories, and a separate command (possibly find again) to print matching files in that directory.

find -type d -exec print-matching-files-in {} \;

If you want to use a find expression to match files, here's a general structure for the second find command to iterate only over non-directories in the specified directory, non-recursively (GNU find required):

find -type d -exec find {} -maxdepth 1 \! -type d … \;

For example:

find -type d -exec find {} -maxdepth 1 \! -type d -iname '.note' \;

In zsh, you can write

print -l **/(#i).note(Od)

**/ recurses into subdirectories; (#i) (a globbing flag) interprets what follows as a case-insensitive pattern, and (Od) (a glob qualifier) orders the outcome of recursive traversals so that files in a directory are considered before subdirectories. With (Odon), the output is sorted lexicographically within the constraint laid out by Od (i.e. the primary sort criterion comes first).


Workaround would be find . -iname '.note' | sort -r:

$ find . -iname '.note' | sort -r
folder/.note
folder/3/.note
folder/2/.note
folder/1/.note

But here, the output is just sorted in reverse order and that does not change find's behaviour.


For me with GNU find on Linux I get both orderings with different test runs.

Testcase:

rm -rf /tmp/depthtest ; mkdir -p /tmp/depthtest ; cd /tmp/depthtest ; for dir in 1 2 3 . ; do mkdir -p $dir ; touch $dir/.note ; done ; find . -iname '.note'

With this test I get the poster's first result. Note the ordering of 1 2 3 .. If I alter this ordering to to . 1 2 3

rm -rf /tmp/depthtest ; mkdir -p /tmp/depthtest ; cd /tmp/depthtest ; for dir in . 1 2 3 ; do mkdir -p $dir ; touch $dir/.note ; done ; find . -iname '.note'

I get the poster's second result.

In either case adding -depth to find does nothing.

EDIT:

I wrote a perl oneliner to look in to this further:

perl -e 'opendir(DH,".") ; print join("\n", readdir(DH)),"\n" ; closedir(DH)'

And I ran this against /tmp/depthtest after running testcase 1 with these results:

.
..
1
2
3
.note

I ran it again after testcase 2 with these results:

.
..
.note
1
2
3

Which confirms that the results are in directory order.

The -depth option to find only controls whether e.g. ./1/.note is processed before or after ./1/, not whether ./.note or ./1/ is first, so the order of the results is purely based on directory order (which is mostly creation order).

It might be helpful to look at How do I recursively list all directories at a location, breadth-first? to learn how to work around this problem.


find -s . -iname ".note" doesn't help? or find . -iname '.note'|sort ?


Find in the current folder

 find ./in_save/ -type f -maxdepth 1| more

==>73!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜