- Exclude Directories While Using Find Command
- Method 1: Using the prune option
- Exclude multiple directories
- Method 2: Using the not operator
- Method 3: Using the ! operator
- Bonus tip: Exclude Subdirectories in find command
- Final Words
- Exclude a sub-directory using find
- 6 Answers 6
- How do I make «find» exclude the folder it searches in?
- 3 Answers 3
Exclude Directories While Using Find Command
By default, find command searches in the specified directory and all its subdirectories. You can refine your search by excluding directories while using find command.
Find is an extremely powerful command for searching for anything you want on your Linux system.
By default, it searches in the specified directory and all its subdirectories.
You may not always want that. You can refine your search by excluding directories from the find command search.
In this tutorial, I’ll show various ways to exclude directories while using the find command.
Method 1: Using the prune option
First, let me bring light to how you’re about to use the find command with the prune option:
find [path] -path [directory to exclude] -prune -o -print
For example, I’ve made a directory named prune which contains the following files and directories:
So how about excluding music directory while performing a search?
find /home/sagar/prune -path /home/sagar/prune/music -prune -o -print
As you can clearly see, it only went through the text and images directory as I excluded the 3rd directory.
Exclude multiple directories
Quite easy right? But what about when you want to exclude multiple directories? That can easily be done using the -o operator.
For example, I’ll be excluding music and text directory:
find . \( -path ./music -prune -o -path ./text -prune \) -o -print
In simple terms, you have to chain your directories with -prune and -o inside () as shown fashion to exclude multiple directories.
But find is not bound to only search for files but when paired with exec, can execute scipts, programs, or even commands over output:
Method 2: Using the not operator
Using the not operator is easy compared to what I explained above as syntax is quite simple to grasp:
find [path] -type f -not -path '*/directory to exclude/*'
For example, let’s exclude the music directory using the not operator:
find . -type f -not -path '*/music/*'
As you can clearly see, the search results do not include any files related to the music directory.
Method 3: Using the ! operator
Yet another easy way to exclude directories while searching is to use the ! operator.
The syntax is similar to what I explained above but a little short in length:
find /path/ -type f ! -path '*/directory to exclude/*'
Let’s say I want to exclude a directory named text so my command would be:
But that’s not it. Being one of the most extensive commands, find can also search for files based on modification time.
Bonus tip: Exclude Subdirectories in find command
Well, this is a bit different as this section is going to utilize the term called search depth .
This means I will be specifying how deeper the find utility will search. Here, deep means the layers of the file system. The general structure of the file system looks like this:
And you can adjust the depth of search by using the maxdepth and mindepth options.
So when you use the maxdepth, you’re giving limits to the find utility, or in simple terms, you’re saying «don’t go any further than this limit».
While mindepth is all about where to start the search and will look for every available file at every layer.
So let’s suppose I want to search for text files that are available at the first layer so I’ll be using maxdepth to control the search:
find . -maxdepth 1 -type f -name "*.txt"
But what if you want to search into a specific layer that sits in the middle? Well, that’s where the mindepth comes to play!
Let’s suppose I want to search for PNG images specifically inside the Images directory (2nd layer) so I will use maxdepth and mindepth to 2 forcing find to search for a specific directory.
find . -maxdepth 2 -mindepth 2 -type f -name "*.png"
Be creative with maxdepth and mindepth and you’ll be able to search for specific files in no time!!
Final Words
This was my take on how to exclude directories while searching files by various methods and if you still have any doubts, feel free to ask in the comments.
Exclude a sub-directory using find
There is an incoming sub-folder in all of the folders inside Data directory. I want to get all files from all the folders and sub-folders except the def/incoming and 456/incoming dirs. I tried out with following command
find /home/feeds/data -type d \( -name 'def/incoming' -o -name '456/incoming' -o -name arkona \) -prune -o -name '*.*' -print
This is not good advice, but it will get you out of a lot of situations quick and dirty: pipe that to grep -v something to exclude whatever it is you don’t want
6 Answers 6
find /home/feeds/data -type f -not -path "*def/incoming*" -not -path "*456/incoming*"
Explanation:
- find /home/feeds/data : start finding recursively from specified path
- -type f : find files only
- -not -path «*def/incoming*» : don’t include anything with def/incoming as part of its path
- -not -path «*456/incoming*» : don’t include anything with 456/incoming as part of its path
@Ravi are you using bash shell? I just tested this on my terminal and it works for me. Try copy and pasting the solution instead if you made modifications to your script.
-path matches the whole string, so if you’re doing find . , then your -path strings need to be ./path/to/directory/*
FYI -not -path definitely will work in this example but find is still iterating into the directory structure and using cpu cycles to iterate over all those directories/files. to prevent find from iterating over those directories/files (maybe there are millions of files there) then you need to use -prune (the -prune option is difficult to use however).
Just for the sake of documentation: You might have to dig deeper as there are many search’n’skip constellations (like I had to). It might turn out that prune is your friend while -not -path won’t do what you expect.
So this is a valuable example of 15 find examples that exclude directories:
To link to the initial question, excluding finally worked for me like this:
find . -regex-type posix-extended -regex ".*def/incoming.*|.*456/incoming.*" -prune -o -print
Then, if you wish to find one file and still exclude pathes, just add | grep myFile.txt .
It may depend also on your find version. I see:
$ find -version GNU find version 4.2.27 Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX
How do I make «find» exclude the folder it searches in?
I would like to delete all the folders under the processing folder (the processing folder should never be deleted). The command is deleting the processing folder as well. How do I limit the script to delete only the folders under that folder?
3 Answers 3
The easiest way would be to just add -mindepth 1 , which will skip the first depth hierarchy and thus leave out your parent directory.
Also, you don’t need an extra -exec call to rm , you can just delete the folders directly if they’re empty.
find /var/www/html/content/processing -mindepth 1 -type d -mtime +1 -delete
find /var/www/html/content/processing -mindepth 1 -type d -mtime +1 -exec rm -rf <> \;
If you’re lazy you can also have a wildcard expanded. Since * doesn’t include the current directory by default (unless dotglob is set), you could also do:
find /var/www/html/content/processing/* -type d -mtime +1 -delete
However, this would also not include hidden folders, again due to the dotglob option.
Hi, I get «find: warning: you have specified the -mindepth option after a non-option argument -type, but options are not positional (-mindepth affects tests specified before it as well as those specified after it). Please specify options before other arguments. » and also «find: cannot delete `/folder/50d82faf0e09e’: Directory not empty»
Add mindepth before type then. To delete the directories when not empty you can stick with the rm approach you had originally.
The problem is that find returns the current directory (.) along with the other directories, so it deletes the processing folder as well as the subdirectories. A quick way to get around that would be to append the option
which stops find from outputting the current directory, and in turn stops it from being deleted.
That would work if you were running the command within the processing directory, so to allow for the fact that you are using an absolute path:
-not -name /var/www/html/content/processing
And the whole command would be:
find /var/www/html/content/processing -type d -mtime +1 -not -name /var/www/html/content/processing -exec rm -rf <> \;
The last command is wrong. -name refers to basename, it never matches anything with a slash. You probably need to use -path .
Already answered, still I would like to list another approach.
find /var/www/html/content/processing -mindepth 1 -maxdepth 1 -type d
This will exclude top directory (and also sub directories), and now you can apply whatever command that we want to apply over it.
>> Options:
-mindepth 1 : To exclude root directory
-maxdepth 1 : To avoid parsing sub directories. (For particular scenario as questioned, you don’t need this).
-type d : List only directory types. This option should come after mindepth maxdepth uses.