Z.J.
Z.J.

Reputation: 69

How to use "find" to prune some directories while keep some subdirectories

There's an example:

#tree
.
├── dir1
│   ├── file1
│   ├── subdir1
│   │   └── file11
│   ├── subdir2
│   │   └── file12
│   ├── subdir3
│   ├── subdir4
│   ├── subdir5
│   └── subdir6
├── dir2
├── dir3
│   └── dir1
│       └── file11
├── dir4
├── dir5
└── dir6

The following command find all files except those under dir1 and dir2.

find -not \( -path './dir1' -prune -o -path './dir2' -prune \)

My question is how to find all files except dir1, dir2 while still search into subdirectory: ./dir/subdir1 ?

I tried some like this, but doesn't work. I don't know what's the right way to combine logical expressions.

find -not \( \
  \( -path './dir1' -a -not -path './dir1/subdir1' \) -prune -o \
  -path './dir2' -prune \)

Forgot to mention that I just wanna know how to use the logical combination in command find: -o -a -not, etc to achieve this. Using filters (grep,sed,awk) after the output of find works, but beyonds my question. Thanks to everyone has posted their answer.


Excepted Output:

.
./dir6
./dir5
./dir4
./dir3
./dir3/dir1
./dir3/dir1/file11
./dir1/subdir1
./dir1/subdir1/file11

Upvotes: 1

Views: 285

Answers (4)

liberize
liberize

Reputation: 21

Maybe you can try:

find . \( -not -path './dir1/*' -and -not -path './dir2/*' -or -path './dir1/subdir1/*' \) -type f

Edit:

Considering prune, I think you should use:

find . \( -path './dir1/*' -and -not -path './dir1/subdir1*' -or -path './dir2' \) -prune -or -type f -print

Upvotes: 2

atupal
atupal

Reputation: 17210

>tree
.
├── dir1
│   ├── file1
│   ├── subdir1
│   │   └── file11
│   ├── subdir2
│   │   └── file12
│   ├── subdir3
│   ├── subdir4
│   ├── subdir5
│   └── subdir6
├── dir2
├── dir3
│   └── dir1
│       └── file11
├── dir4
├── dir5
└── dir6

13 directories, 4 files

>find | awk '
  {
    if($1 !~ /^\.\/dir1$/ && $1 !~ /^\.\/dir2$/) {
      if ($1 ~ /^\.\/dir1\//) {
        if ($1 ~ /^\.\/dir1\/subdir1(\/|$)/) {
          print($1)
        }
      } else if ($1 !~ /\.\/dir2\//) {
        print($1)
      }
    } 
  } '
.
./dir6
./dir5
./dir4
./dir3
./dir3/dir1
./dir3/dir1/file11
./dir1/subdir1
./dir1/subdir1/file11

Upvotes: 0

merlin
merlin

Reputation: 69

man find

-mindepth levels
              Do not apply any tests or actions at levels less than levels (a  non-negative  integer).-min-depth 1 means process all files except the command line arguments.

this is not test!

find dir1 -mindepth N -type f

Upvotes: 0

BMW
BMW

Reputation: 45243

Try this:

find . -type f |sed '/.\/dir[12]\/[^/]*$/d'

Upvotes: 0

Related Questions