How do I exclude a directory when using `find`?
Use the -prune
primary. For example, if you want to exclude ./misc
:
find . -path ./misc -prune -o -name '*.txt' -print
To exclude multiple directories, OR them between parentheses.
find . -type d \( -path ./dir1 -o -path ./dir2 -o -path ./dir3 \) -prune -o -name '*.txt' -print
And, to exclude directories with a specific name at any level, use the -name
primary instead of -path
.
find . -type d -name node_modules -prune -o -name '*.json' -print
Finding directories with find in bash using a exclude list
Try something like
find /var/www/* \( -path "${Iggy[0]}" $(printf -- '-o -path "*%s" ' "${Iggy[@]:1}") \) -prune -type d
and see what happens.
EDIT: added the leading * to each path as in your example.
And here's a complete solution based on your description.
#!/usr/bin/env bash
basepath="/home/adesso/baldar"
ignore=("/cgi-bin" "/tmp" "/test" "/html" "/icons")
find "${basepath}" -maxdepth 1 -not \( -path "*${ignore[0]}" $(printf -- '-o -path "*%s" ' "${ignore[@]:1}") \) -not -path "${basepath}" -type d
Subdirectories of $basepath excluding those listed in $ignore, presuming at least two in $ignore (fixing that is not hard).
Use find command but exclude files in two directories
Here's how you can specify that with find
:
find . -type f -name "*_peaks.bed" ! -path "./tmp/*" ! -path "./scripts/*"
Explanation:
find .
- Start find from current working directory (recursively by default)-type f
- Specify tofind
that you only want files in the results-name "*_peaks.bed"
- Look for files with the name ending in_peaks.bed
! -path "./tmp/*"
- Exclude all results whose path starts with./tmp/
! -path "./scripts/*"
- Also exclude all results whose path starts with./scripts/
Testing the Solution:
$ mkdir a b c d e
$ touch a/1 b/2 c/3 d/4 e/5 e/a e/b
$ find . -type f ! -path "./a/*" ! -path "./b/*"
./d/4
./c/3
./e/a
./e/b
./e/5
You were pretty close, the -name
option only considers the basename, where as -path
considers the entire path =)
find directories but exclude list where directories have a space in name
You could read the exclude file into a Bash array and then craft a find
command like this:
mapfile -t exclude < exclude.txt
find ./base_dir \
-mindepth 1 \ # Exclude the current directory
-type d \
-regextype egrep \ # Make sure alternation "|" does not have to be escaped
! -iregex ".*/($(IFS='|'; echo "${exclude[*]}"))" \
-printf '%f\n' # Print just filename without leading directories
resulting in
sub_dir1
sub_dir4
For your example input, the -iregex
test expands like this:
$ IFS='|'
$ echo "${exclude[*]}")
sub_dir2|sub dir3
so the regular expression for paths to exclude becomes
.*/(sub_dir2|sub dir3)
The change to IFS
is limited to the command substitution.
The limitation to this is if the directories to be excluded contain characters that are special to regexes, you have to escape those, which can get messy. If you wanted to escape, for example, pipes, you could use
echo "${exclude[*]//|/\\|}"
in the command substitution, resulting in
sub_dir2|sub dir3|has\|pipe
where the directory has|pipe
with a |
in its name has its pipe properly escaped.
Exclude a sub-directory using find
This works:
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 withdef/incoming
as part of its path-not -path "*456/incoming*"
: don't include anything with456/incoming
as part of its path
Exclude a directory from find linux
with -prune
find . -name directory_to_exclude -prune -o ...
to exclude many directories
find . \( -name dir1_to_exclude -o -name dir2 ... \) -prune -o ...
Exclude range of directories in find command
You can use wildcards in the pattern for the option -not -path
:
find ./ -type f -name "*.bz2" -not -path "./0*/*" -not -path "./1*/*
this will exclude all directories starting with 0 or 1. Or even better:
find ./ -type f -name "*.bz2" -not -path "./[01]*/*"
Exclude list of files from find
I don't think find
has an option like this, you could build a command using printf
and your exclude list:
find /dir -name "*.gz" $(printf "! -name %s " $(cat skip_files))
Which is the same as doing:
find /dir -name "*.gz" ! -name first_skip ! -name second_skip .... etc
Alternatively you can pipe from find
into grep
:
find /dir -name "*.gz" | grep -vFf skip_files
Exclude folders when using find
You can use the -path
option to exclude certain directory paths in your search:
find / -iregex ".*\.py" ! -path "/your/django/directory"
And you can chain this multiple times if you want to exclude multiple directories:
find / -iregex ".*\.py" ! -path "/your/django/directory" ! -path "/another/dir"
Excluding an array/list of directories in find
If it works, just add !
and -path
in front of every element of the array and pass it to find
.
excludedDirList2=('*.' 'node_modules')
findargs=()
for i in "${excludedDirList2[@]}"; do
findargs+=('!' '-path' "$i")
done
find "$dir" -type f -name "hidden.txt" "${findargs[@]}"
Related Topics
Getting "Permission Denied" on Dirname and Basename
Linux: How to Check The Largest Contiguous Address Range Available to a Process
How Event Packet Header Is Getiing in Hci_Send_Req API Implementation
Starting Multiple Firefox Profiles with Batch File in Linux
Building Robert Nelson's Linux Kernel into Yocto(Daisy) for Beaglebone Black
Understanding The Netstat Output
Touch Command Create Multiple Files (Different Names) Under One Directory
How to Generic .Htaccess to Prevent Hotlink
Releasing All Keys After Disabling The Keyboard in X11/Linux Using Xinput
Linux Usb Driver Probe Not Called If Device Already Plugged
Polling a Loop Device Through a Kernel Module
Expect Utility Is Not Working When Executing from Jenkins
How to Set The Current Directory of a Debugged Process
How Is an Error Reported from Async Socket Connect
Where Is The Linux Socket Implementation