Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to skip multiple directories when doing a find

I've written a find function that searches for a string in each file in a given path, while skipping a list of directory names that I don't want searched. I've placed this script in my .bashrc file to be called like so:

findTEXTinFILES /path/to/search 'text-to-find'

The find portion works great, and it colorizes the search text so that it visually stands out!, but I can't get it to skip the directories listed with -prune. I've read all the posts here that I can find but none work for me. I've tried multiple variations with no luck. So I have a few questions:

  • How do you skip multiple directories?
  • How do you skip directories with just a partial name, such as those that begin with '--' or 'wp-'?
  • Can you mix -name and -path criteria in the same script?
  • Is there something else I've missed?

My server is CENTOS 6.9 virtuozzo with the bash shell.

function findTEXTinFILES {

find "$1" ! \( -name .bash_history -prune \
    -o ! -path tmp -prune \
    -o ! -path short -prune \
    -o ! -path "*/_not_used/*" -prune \
    -o ! -path backups -prune \
    -o ! -path temp_logs -prune \
    -o ! -name .cpan -prune \
    -o ! -name .cpobjcache -prune \
    -o ! -path files_to_compare -prune \
    -o ! -path logs -prune \
    -o ! -path mail -prune  \
    -o ! -path old -prune \
    -o ! -path '--*' -prune \
    -o ! -path 'wp-*' -prune \
    -o ! -path '*copy*' -prune \) \
    -o -name "*" \
    -exec grep $2 -I --color -Hn '$3' '{}' 2>/dev/null \;
}
like image 696
Frank Jance Avatar asked Dec 13 '17 17:12

Frank Jance


People also ask

How do you jump between directories in Linux?

The cd (change directory) command moves you into a different directory. To move out of that directory, use cd along with the path to some other location, or use double dots to backtrack, or return home to navigate from there.

How do I jump to a directory?

You can use cd .. to move one directory back, or cd ./path/to/another/folder to jump through many folders into a specific location.

How do I exclude a file path?

To exclude specific files, in the Files text box, type the file names and paths to exclude, separated by commas. For example, C:\windows\system32\filename. dll. You can include question mark and asterisk wildcards.

How do I switch between folders?

Here are the different ways to change your CMD directory in Windows 10 or Windows 11: Open the Command prompt, type in cd followed by the directory you want to move into, and hit Enter. Change the Windows directory by entering the drive name followed by : in the Command prompt, and hit Enter.


1 Answers

A find expression is composed primarily of tests and actions joined together with operators. It is evaluated in a standard short-circuiting manner -- meaning the evaluation is stopped as soon as the result is known, without the need to evaluate all parts (e.g. true or anything is evaluated to true).

Now note that -prune is an action that always returns true. It can act on the result of any test. Also note that the default operator is -a (and).

So, the simplest pruning example, to print all files except those under some path (e.g. wp-* in your example) looks like:

find . -path './wp-*' -prune -o -print

For files matching the path starting with ./wp-, prune action is executed, meaning the result is true, and the right part of the OR operator can be ignored (i.e. file is not printed). Note here that -path matches relative path, in this case rooted at ., so we have to write ./wp-* instead of wp-*.

To prune two paths, simply extend:

find . -path './wp-*' -prune -o -path ./logs -prune -o -print

Here: if first prune action is not executed (result false), then a chance is given to the second, if that doesn't prune neither (result false), then -print action is executed. In case any -prune gets evaluated, -print doesn't get a chance.

Applying this to your case:

find "$1" -name .bash_history -prune \
    -o -path "$1/tmp" -prune \
    -o -path "$1/short" -prune \
    -o -path "$1/*/_not_used/*" -prune \
    -o -path "$1/backups" -prune \
    -o -path "$1/temp_logs" -prune \
    -o -name "$1/.cpan" -prune \
    -o -name "$1/.cpobjcache" -prune \
    -o -path "$1/files_to_compare" -prune \
    -o -path "$1/logs" -prune \
    -o -path "$1/mail" -prune  \
    -o -path "$1/old" -prune \
    -o -path "$1/--*" -prune \
    -o -path "$1/wp-*" -prune \
    -o -path "$1/*copy*" -prune \
    -exec grep $2 -I --color -Hn '$3' '{}' 2>/dev/null \;

To avoid writing $1-dependent paths, you can cd "$1" and use f.e. find . ... -path ./logs ....

like image 74
randomir Avatar answered Sep 27 '22 22:09

randomir