Reputation: 77
I'd like to use find command with excluding a directory.
I have this:
GLUE="$GLUE -not -iwholename */dir3/*"
And I want to use a GLUE
variable in a find
command (find $GLUE [...]
). Unfortunately, instead of -not -iwholename */dir3/*
in GLUE
I get -not -iwholename dir3/file1 dir3/file2 dir3/file3
, i.e., */dir3/*
turns into names of files which meet this condition. And, of course, find
doesn't work because of it. How to stop that?
Upvotes: 2
Views: 190
Reputation: 46813
Let me answer this question first:
How can I use
find
to search recursively while excluding a directory from the search? Myfind
command supports the-prune
action and the common extensions (e.g., provided by GNUfind
).
You're very lucky that your find
supports the -prune
action. Congratulations!
In this case, only add:
\! \( -name 'dir_to_exclude' -prune \)
This will be false if the current name processed by find
is dir_to_exclude
, and at the same time prune (i.e., cut that branch) from the search tree1.
Let's try it (in a scratch directory):
$ mkdir {a,b,c,d}/{,1,2,3}
$ touch {a,b,c,d}/{,1,2,3}/{file1,file2}
$ tree
.
|-- a
| |-- 1
| | |-- file1
| | `-- file2
| |-- 2
| | |-- file1
| | `-- file2
| |-- file1
| `-- file2
|-- b
| |-- 1
| | |-- file1
| | `-- file2
| |-- 2
| | |-- file1
| | `-- file2
| |-- file1
| `-- file2
`-- c
|-- 1
| |-- file1
| `-- file2
|-- 2
| |-- file1
| `-- file2
|-- file1
`-- file2
9 directories, 18 files
$ find \! \( -name a -prune \)
.
./b
./b/file2
./b/1
./b/1/file2
./b/1/file1
./b/file1
./b/2
./b/2/file2
./b/2/file1
./c
./c/file2
./c/1
./c/1/file2
./c/1/file1
./c/file1
./c/2
./c/2/file2
./c/2/file1
Looks good!
Now, you shouldn't put your arguments to find
(or, more generally your commands and arguments) in a variable, but in an array! If you don't you'll very soon run into problems with arguments containing spaces or, like in your OP, wildcards.
Put your glue
stuff in an array: for example, to find all the files that have a 1
in their name and are empty2:
glue=( '-name' '*1*' '-type' 'f' '-empty' )
Then an array of the exclude this directory:
exclude_dir=( '!' '(' '-name' 'a' '-prune' ')' )
Then find all files that have a 1
in their name and are empty, while excluding directory a
(in the same scratch directory as before):
$ find "${exclude_dir[@]}" "${glue[@]}"
./b/1/file1
./b/file1
./b/2/file1
./c/1/file1
./c/file1
./c/2/file1
Looks really good! (and observe the quotes!).
1
If you really want to be sure that you're only excluding the directory with name dir_to_exclude
, in case you have a file called dir_to_exclude
, you can specify it thus:
\! \( -name 'dir_to_exclude' -type d -prune \)
2
I'm using a lot of quotes here. Just a good habit that actually saves me for the wildcard part *1*
and for the parentheses too!
Upvotes: 2
Reputation: 2160
find ./ -iname ! -iname <dirname of file name to be not part of search results>
find ./ -iname <file name> ! -path "./dirt o be Excluded/*"
I hope one will help
Upvotes: 2