LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   Telling find command to ignore directories (https://www.linuxquestions.org/questions/linux-software-2/telling-find-command-to-ignore-directories-533853/)

LinuxGeek 03-02-2007 05:39 AM

Telling find command to ignore directories
 
Hi,
I'm trying to get the find command to ignore certain directories when searching. I looked in the man page and it recommended -wholename and prune but I tried both and they don't seem to work. What I'm trying to do is something like this:

find / -iname \*.iso

but I don't want to search in certain directories such as /share, etc. (all of them are on the same filesystem so I can't use -xdev). Any ideas? Thanks for your help.

pk2001 03-02-2007 05:54 AM

Quote:

Originally Posted by LinuxGeek
Hi,
I'm trying to get the find command to ignore certain directories when searching. I looked in the man page and it recommended -wholename and prune but I tried both and they don't seem to work. What I'm trying to do is something like this:

find / -iname \*.iso

but I don't want to search in certain directories such as /share, etc. (all of them are on the same filesystem so I can't use -xdev). Any ideas? Thanks for your help.

I had to do something similar recently. Also I could not find a way to instruct "find" to ignore directories.... However, I solved this by piping the find result to "grep" and instructing grep to ignore certain keywords. For example:

Quote:

Originally Posted by pk2001
find / -name "*.txt"|grep -ve "/usr/share/" -e "/usr/lib/" -e "/var/www/"

This find command will find all the text files that exist in the root directory and any subdirectories, EXCEPT in /usr/share, /usr/lib/ and /var/www

Bear in mind that it is the "-v" switch for grep that really saves you here.

jay73 03-02-2007 05:55 AM

You can specify the directories you do want to search. For example:

find /home /var /tmp -name '*iso'

LinuxGeek 03-02-2007 10:01 AM

Thanks for your replies. It seems that it's best to pipe to grep or use xargs. jay73, the problem with the suggested approach above is if the directory you want to exclude is a subdirectory of a directory that you want to search. In that case (which is my case), you would have to either:

a) use grep

b) use xargs

c) try to find out how to do it natively with find

colucix 03-02-2007 07:52 PM

I think the -wholename -prune approach is the most reliable! Let me do an example. Suppose I have a directory called /test containing three files
Code:

> ls -1 -F /test
apple
pine
pineapple

If I issue the find command I will get four entries
Code:

> find /test
/test
/test/pine
/test/pineapple
/test/apple

Now, let's start from the option -wholename pattern. Only the entries matching the pattern will be listed. The whole entries!!!
Code:

> find /test -wholename pine
>

Nothing! Indeed, there is no entry that matches exactly pine. Now, let's add wildcards to the pattern.
Code:

> find /test -wholename \*pine\*
/test/pine
/test/pineapple

Here there are two entries that match pine with something before and/or something after! Now, let's create a directory inside /test and put duplicates of the same three files inside it. Then issue the find command.
Code:

> mkdir /test/newdir
> touch /test/newdir/pine
> touch /test/newdir/pineapple
> touch /test/newdir/apple
> find /test
/test
/test/pine
/test/newdir
/test/newdir/pine
/test/newdir/pineapple
/test/newdir/apple
/test/pineapple
/test/apple

Now, let's try the find command with the two wildcards again. Then issue the find command using the name of a directory as pattern!
Code:

> find /test -wholename \*pine\*
/test/pine
/test/newdir/pine
/test/newdir/pineapple
/test/pineapple
> find /test -wholename /test/newdir
/test/newdir

The former has retrieved two of the new files, as expected. The latter has retrieved the entry matching exactly /test/newdir.
Now the intersting part: let's introduce the option -prune (literally to cut off branches from a tree)! First note that -prune is an ACTION (like -print) and not a TEST (like -wholename). This means that -prune performs a task, it is not something to evaluate! This task is: if an entry is a directory do not descend into it. Let's try
Code:

find /test -wholename /test/newdir -prune
/test/newdir

here the test is true (the entry /test/newdir matches the pattern) but since we have not searched for anything else, the result is not meaningful. Actually the rule is if the expression contains no actions other than -prune, -print is performed on all files for which the expression is true.
The utility of -prune is clear, if we add another expression by means of the OPERATOR expr1 -o expr2
Code:

> find /test -wholename /test/newdir -prune -o -print
/test
/test/pine
/test/pineapple
/test/apple

here we have -prune and -print, so the /test/newdir entry is not printed anymore; the directory /test/newdir is excluded from the search path; any other entry whose wholename does not match exactly /test/newdir is printed. Now add a TEST to the second expression
Code:

> find /test -wholename /test/newdir -prune -o -name apple -print
/test/apple

the trick is done! We have found a file called apple excluding that one inside /test/newdir. If you want to exclude more than one directory you can do
Code:

find /test \( -wholename /test/newdir -o -wholename /test/pippo \) -prune -o -name apple -print
that is in the first expression you will put two TESTS enclosed in escaped ( ) and separated by the OPERATOR -o. Finally, in your example you will have something like
Code:

find / \( -wholename /share -o -wholename /lib -o -wholename /bin \) -prune -o -iname \*.iso -print
I hope these options are a little more clear now, despite my bad english! Sorry for the very long post! :)

jschiwal 03-02-2007 08:33 PM

If you use grep to filter the output, the directories like /usr will still be searched which may take some time.
It would be better having an idea on which part of the filesystem the file exists in.
The command "find /home/ /tmp -iname "*.iso" would be better then "find / "*.iso".

If you install the source for the find command, you can use the "make pdf" target to generate the "Finding Files" document from the texinfo source. It is 60 pages long.

LinuxGeek 03-03-2007 01:28 AM

Thank you very very much colucix for your detailed example :) Thank you also jschiwal for your comment.

sharky 04-28-2008 01:35 PM

type is ignored
 
I used a command somewhat like this to filter out some huge directories.

find . -type d \( -name '*core*' \) -prune -o -print

All directories with *core* in the name were pruned as I desired but the final output included files and directories. Why would the -type switch be ignored?

osor 04-28-2008 01:56 PM

Quote:

Originally Posted by sharky (Post 3135767)
Why would the -type switch be ignored?

It is in the first branch of an “or” test. So it is like,
Code:

if(matches)
    prune
else
    print

Since we are reviving this thread, I might point out a much simpler alternative to using prune is just a negated pattern match. E.g.,
Code:

find / ! -wholename '*/share/*' -name '*.iso'
(where the ‘!’ may or may not need escaping).

rsashok 11-10-2009 12:35 PM

On the system I'm using 'find' doesn't have '-wholename' predicate. (apparently older version of binutils). I try to skip directories that start with '.svn', and that worked for me:

Quote:

find . -type d \( -name '\.svn*' \) -prune -o -type d -print
I am not sure how and why it works in this shape and form, but it is worthwhile trying.

amarh123 08-17-2011 08:39 AM

find [source dir] -path [source dir]/[sub dir 1] -prune -o -path [source dir]/[sub dir 2] -prune -o -name [filename]


All times are GMT -5. The time now is 08:28 AM.