9

I need to backup all the directory hierarchy of our servers, thus I need to list all the sub directories of some of the directories in the server.

The problem is that one of those sub directories contains tens of thousands of sub directories (file with only the names of the sub directories could take couple of hundreds megabytes and the respective find command takes very long).

For example, if I have a directory A and one sub directory A/a that contains tens of thousands of sub directories, I want to use the find command to list all the sub directories of A excluding all the sub directories of A/a but not excluding A/a itself.

I tried many variations of -prune using the answers in this question to no avail.

Is there a way to use the find command in UNIX to do this?

UPDATE:

the answer by @devnull worked very well, but now i have another problem, so i will refine my question a little:

i used the following command:

 find /var/www -type d \( ! -wholename "/var/www/web-release-data/*"  ! -wholename "/var/www/web-development-data/*" \)

the new problem that arises is that find for some reason is still traversing the whole directory tree of "/var/www/web-release-data/" and "/var/www/web-development-data/", thus it's very slow, and I fear it could take hours.

Is there any way make find completely exclude those directories and not traverse their respective directory hierarchies?

Community
  • 1
  • 1
DontCareBear
  • 825
  • 2
  • 11
  • 25

5 Answers5

2

The following should work for you:

find A -type d \( ! -wholename "A/a/*" \)

This would list all subdirectories of A including A/a but excluding subdirectories of A/a.

Example:

$ mkdir -p A/{a..c}/{1..4}
$ find A -type d \( ! -wholename "A/a/*" \)
A
A/c
A/c/4
A/c/2
A/c/3
A/c/1
A/a
A/b
A/b/4
A/b/2
A/b/3
A/b/1
devnull
  • 118,548
  • 33
  • 236
  • 227
  • +1 Note: No need for the parentheses, here. They just make the intent more clear. – Aaron Digulla Sep 10 '13 at 15:46
  • how can i exclude two sub dirs using your method? – DontCareBear Sep 10 '13 at 15:52
  • 1
    In order to exclude all subdirectories of `A/b` in the above example, say `find A -type d \( ! -wholename "A/a/*" ! -wholename "A/b/*" \)` – devnull Sep 10 '13 at 15:55
  • it looks like its working but i think find is still traversing the whole list of sub directories of A/a and A/b, and its still not finished (its very very slow). is there a way to make find skip A/a, A/b completely without traversing their dir tree? – DontCareBear Sep 10 '13 at 16:01
1

Another solution:

find A \! -path "A/a/*"

If you don't want a as well, use

find A \! -path "A/a/*" -a \! -path "A/a"
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
0

Have you tried rsync(1)? It has an option --exclude=PATTERN which might work well here:

rsync -avz --exclude=A/a <source> <target>

Using rsync you wouldn't need to use find(1)

Stuart M
  • 11,458
  • 6
  • 45
  • 59
0

To exclude 2 subdirs:

find . -type d ! -wholename "dir/name/*" -a ! -wholename "dir/name*"
Fraser11
  • 1
  • 1
0

To answer your updated question, you can do

find /var/www -wholename "/var/www/web-release-data/*" -o -wholename "/var/www/web-development-data/*" -prune -o -type d -print
Aaron Okano
  • 2,243
  • 1
  • 12
  • 5
  • i tried it, and it still takes to much time (i killed the process after ten minutes). find still traverses all the directory tree of /var/www/web-release-data/ which contains tens of thousands of sub dirs. – DontCareBear Sep 17 '13 at 13:35