Home > Software design >  How do I include a list of sub-directories when using `find`?
How do I include a list of sub-directories when using `find`?

Time:01-24

Although I could not find an example of what I want to achieve, I thought this would be easy given examples that would appear to have similar logic, eg How do I exclude a directory when using find?, How to only find files in a given directory, and ignore subdirectories using bash, How to combine 2 -name conditions in find?. Yet again, I have been proven wrong :(

I have a number of directories under /data/csvfiles

cd /data/csvFiles/
ls -l
drwxr-x---. dir1
drwxr-x---. dir2
drwxr-x---. dir3
drwxr-x---. dir4
drwxr-x---. dir5
drwxr-x---. dir6
drwxr-x---. dir7

I would like to find all *.gz files within directories dir2, dir3, dir5, dir7

As you may guess, the directories have different names to that illustrated. (Also, my find is much more complex to that being discussed. The bash script asks for start and end times, and pipes to a zgrep, being passed to a list of server names for ssh.). I have included a simple pipe to 'sort' to represent this.

Starting with the basics

find /data/csvFiles/ -type f -name "*.gz" | sort

Reading the linked discussion, my first attempt is

find /data/csvFiles/ -type d \( -path ./dir2 -o -path ./dir3 -o -path ./dir4 \) -type f -name "*.gz" | sort

This returns nothing, which I believe is due to the use of ./ I then cautiously backtrack to a single directory before attempting a list. hoping the use of *dir* will make it 'relative' to /data/csvFiles.

find /data/csvFiles/ -path '*dir2*' -type f -name "*.gz" | sort

This works, but notice that I have switched from -type d to -path (reading the answers to different questions).

I then try and combine the working (using -path) example with the format provided in an answer which uses a list

find /data/csvFiles/ -type d \( -path '*dir2*' \) -type f -name "*.gz" | sort

Again, nothing is returned, although I know files name *.gz exist in /data/csvFiles/dir2.

I have tried many combinations and would be grateful if someone can explain how to add a list of subdirectories, which I would guess is something like

find /data/csvFiles/ -type d \( -path '*dir2*' -o -path '*dir2*' -o -path '*dir3*' -o -path '*dir5*' -o '-path *dir7*' \) -type f -name "*.gz" | sort

CodePudding user response:

Although I am unsure why type -d does not appear to work with -path, I am guessing the community believes my question does not warrant a response, as the answer is fairly simple. Stepping away from the linked discussions, it occurred to me that I only need the -path 'test'.

find /data/csvFiles/ \( -path '*dir2*' -o -path '*dir2*' -o -path '*dir3*' -o -path '*dir5*' -o '-path *dir7*' \) -type f -name "*.gz" | sort

I believe the above works... (although I actually have /data/csvFiles/tmp/dir2 which messes things up. Ideally, I only want to test the first directory level after start point, but -depth appears to clash. However, that is a different question. NB I know about -prune, but I am wondering if it is possible to test by depth).

EDIT I am wrong again, -maxdepth does work. I thought it would be relative to the start position, which it is, but it appears the start position is 1, and the proceeding level makes 1 1.

find /data/csvFiles/ -maxdepth 2 \( -path '*dir2*' -o -path '*dir2*' -o -path '*dir3*' -o -path '*dir5*' -o '-path *dir7*' \) -type f -name "*.gz" | sort

The above is the solution I was looking for.

  • Related