1610

I'm trying to run a find command for all JavaScript files, but how do I exclude a specific directory?

Here is the find code we're using.

for file in $(find . -name '*.js')
do 
  java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file
done
leiyc
  • 881
  • 6
  • 19
helion3
  • 27,515
  • 13
  • 48
  • 91
  • 11
    What's the directory you need to exclude? – The Archetypal Paul Nov 17 '10 at 23:00
  • 13
    It's better to use `find ... | while read -r file ...`. Also, it's better to accept and upvote answers. – Dennis Williamson Nov 17 '10 at 23:26
  • while read is slow, for in is faster – mpapis Nov 18 '10 at 17:08
  • 18
    @mpapis while read correctly handles full lines with whitespace. – Jean-Philippe Pellet Aug 16 '12 at 10:44
  • I tried to exclude the /proc dir to avoid permission denied errors hiding my results, but it didn't work; this is how I achieved it: http://stackoverflow.com/questions/762348/how-can-i-exclude-all-permission-denied-messages-from-find – Highly Irregular Jul 23 '13 at 19:40
  • find . -name "*.so" -type f (ignore folders) – Dawid Drozd Jul 08 '14 at 13:37
  • @Jean-PhilippePellet What does it mean that it correctly handles full lines with whitespace? Can you give an example of when `for file in $(find ...); do ...; done` would fail? – HelloGoodbye Dec 02 '15 at 09:54
  • 1
    Just run this in a folder with files with spaces in their names: `for file in $(find .); do echo "$file"; done`. Names with spaces are split, which we don't want. – Jean-Philippe Pellet Dec 02 '15 at 10:09
  • Remember to not have "/" on the end or it will return all of files in the folder... so like this; find /home/mquick/watch_folder -not \( -path "/home/mquick/watch_folder/aws_restore_tool.bash_restore_folder" -prune \) -exec bash -c 'echo "$0"' {} \; – Mike Q Jul 09 '16 at 17:58
  • Use `-path -prune` to exclude the dir contents, and add `-type f` remove the unwanted dir name itself from the results: `find -path '*/ignoredirname' -prune -type f -o -name '*.js'` – Brent Faust Jan 16 '19 at 19:18
  • There is a modern alternative to `find`: [fdfind](https://github.com/sharkdp/fd) which `excludes by default hidden files`. Should I post new answer? – Timo May 17 '21 at 17:28

42 Answers42

2153

If -prune doesn't work for you, this will:

find -name "*.js" -not -path "./directory/*"

Caveat: requires traversing all of the unwanted directories.

Mateen Ulhaq
  • 18,406
  • 13
  • 75
  • 112
GetFree
  • 34,030
  • 17
  • 70
  • 101
  • 3
    Describe why they're wrong? I've been using the chosen answer for two and a half years now... – helion3 Apr 01 '13 at 03:31
  • 93
    One of the comments in the accepted answer points out the problem. `-prune` does not exclude the directory itself, it exclude its content, which means you are going to get an unwanted line in the output with the excluded directory. – GetFree Apr 01 '13 at 08:20
  • 121
    Great answer. I'd add to this that you can exclude a directory at ANY level by changing the first `.` to `*`. so `find -name "*.js" -not -path "*/omitme/*"` would omit files from a directory named "omitme" at any level of depth. – DeeDee May 01 '13 at 02:51
  • 90
    It still *traverses* all of the unwanted directory, though. I'm adding my own answer. :-) – Daniel C. Sobral May 16 '13 at 18:52
  • 20
    Note, however, that the prune option only doesn't work if you don't use `-print` explicitly. – Daniel C. Sobral May 16 '13 at 19:07
  • 40
    It would be better to say "This is an alternative to using -prune". The answers suggesting -prune are clearly not wrong, they just aren't the way you would do it. – Jimbo Aug 16 '13 at 08:27
  • 3
    @Jimbo, yes they are wrong. Read the comments in the accepted answer and this one or try them yourself to check it. – GetFree Sep 12 '13 at 21:48
  • 3
    @GetFree: As the original author of the infamous "prune" answer: No they are not wrong. To test your claim, I just created a test directory, created 5 js files inside, created a testtest subdirectory right beside them and copied the js files into the subdirectory. I ran both commands (prune and your) and they both return the exact same output: http://pastebin.com/eH4tvgSh – f10bit Sep 26 '13 at 12:35
  • 4
    @f10bit, a previous comment to this answer explains why it worked for you. The `-prune` option only works if you use `-print` as the action. If you want to do anything else, it doesn't work properly. That's why all answers using `-prune` are wrong for the general case (they would work in one specific case only). – GetFree Sep 26 '13 at 23:14
  • 2
    Using prune works fine for me, even with an `exec` or `ls` action. Am I misreading something, or are you asserting the man page is wrong? From the man page (GNU findutils 4.4.2 - Ubuntu 12.04 Precise): "To ignore a whole directory tree, use -prune rather than checking every file in the tree. For example, to skip the directory `src/emacs` and all files and directories under it, and print the names of the other files found, do something like this: `find . -path ./src/emacs -prune -o -print`" – jbo5112 Dec 09 '13 at 16:07
  • 7
    -1: A good answer must avoid traversing below the unwanted directories. It's one of the main use-cases going beyond the particulars of the original question. – Evgeni Sergeev Feb 07 '14 at 22:02
  • 1
    Works for me on RHEL 6, whereas `-prune` did not (even with `-print`) – xav Mar 13 '14 at 12:08
  • 1
    I think maybe what he means by "wrong" are "stupid and inefficient". He was just being polite. – Buttle Butkus Mar 18 '14 at 02:13
  • 4
    @ButtleButkus Except `-prune` is more efficient. He is wrong in using `wrong`, it's as simple as that. – Reinstate Monica Please Sep 30 '14 at 20:48
  • 4
    @pal4life Use `!`, which is posix compliant. – Reinstate Monica Please Sep 30 '14 at 20:51
  • 1
    The use of `-prune` is not only more efficient, it's also inline exactly with the man page (referenced in `-name`, `-wholename`, and `-prune`). :-) – Hossy Oct 18 '14 at 22:33
  • 3
    Doesn't prune not work when used in concert with `-depth` and as a side effect not work correctly with other commands which imply `-depth`? IIRC there is even a warning about this in the manpage for find. – Dave Rawks Jun 22 '15 at 17:18
  • 5
    -1 The use of `prune` is definitely what the original autor looks for. The [currently accepted answer](http://stackoverflow.com/a/4210072/413020) prints out the pruned dir, but that doesn't mean that it's wrong. The author wanted to compress some files. That can be achieved by an `-exec` in the right side of the `-o`, and it will work flawlessly. I'm amazed how many upvotes has become this answer. If you don't even want to print the pruned dir, you could also tune that. Better improve the accepted answer. – Alberto Aug 28 '15 at 08:00
  • 1
    Thanks. This answer worked in 5 seconds to dump changelog without fiddling around much...prune was outputting unexpected results (or lack of file ext): `# find /searched-directory -type f -not -path "/ignored-directory1/*" -not -path "/ignored-directory2/*" -not -path "/ignored-directory3/*" -printf '%TY-%Tm-%Td %TT %p\n' | sort -r > /export-directory/changedump.txt` – dhaupin Nov 17 '15 at 15:24
  • 8
    KEY TAKE AWAY: "**It still traverses all of the unwanted directory, though**" --> results are the same but time is very different. for me the difference was: **2 minutes vs 8 seconds**. Using the `-prune` is more difficult IMO but makes execution time *much* faster. – Trevor Boyd Smith Nov 04 '16 at 17:21
  • 1
    this is not working for me to exclude node_modules => " find $(dirname "$DIR")/**/**/*.js -maxdepth 8 -type f -not -path "*/node_modules/*" ....kind of sad that it doesn't work TBH – Alexander Mills Dec 15 '16 at 09:06
  • 4
    `!` is more concise than `-not`. – Quolonel Questions Jun 04 '17 at 22:02
  • 1
    @GetFree “all answers using -prune are wrong for the general case” No, not all. `find`’s primary and most general use-case is *finding files.* Use-cases outside of that—deleting, exec-ing, etc.—are extras and nice-to-haves. They’re built-in—in spite of the challenge their inclusion poses to the UNIX “one thing” philosophy—primarily for convenience/historical purposes. But they’re not `find`’s primary role&responsibility. Incidentally, this is why piping `-print`’d `find` output to something like a while loop is usually better when you need to do anything more complex with the discovered files. – Mark G. Jun 16 '17 at 16:00
  • @MarkG. you made up that quote yourself. I've never said that. – GetFree Jun 17 '17 at 14:57
  • `-prune` definitely works. The problem is that the Accepted Answer by f10bit isn't totally correct. Try this solution with a working example: https://stackoverflow.com/a/47341478 – wisbucky Nov 17 '17 at 00:43
  • 1
    I like this answer, but how can I modify it to exclude multiple specific directories instead of just one? – still_dreaming_1 Dec 09 '17 at 01:02
  • 5
    @still_dreaming_1, just repeat the part `-not -path "./dir_name/*"` – GetFree Dec 09 '17 at 13:39
  • Is there any way to detect all the folder having a specific folder name instead of its path ? @GetFree – alper Aug 03 '18 at 22:19
  • 1
    @alper, the third comment to this answer (by DeeDee) might help you. – GetFree Aug 04 '18 at 15:24
  • @GetFree “you made up that quote yourself” *Au contraire.* For context, my comment was in reference to [this](https://stackoverflow.com/questions/4210042/how-to-exclude-a-directory-in-find-command/15736463#comment28137557_15736463). My point was that `-prune` *is* the general case. It’s `-not -path` or `! -path` that are exceptional, such as when one is using an action (like `-delete`) that implies `-depth` (which is antithetical to general-purpose `-prune`). Neither are wrong, but one would be well-advised to use the right tool for the job. If `-depth` is not needed/implied, that’s `-prune`. – Mark G. Aug 09 '18 at 14:19
  • @MarkG. that comment was posted long, long time ago when in fact all answers to this question that proposed using `-prune` where wrong. Since then, a few new answers have been posted that use `-prune` correctly. – GetFree Aug 09 '18 at 16:59
  • this doesn't work for me in Ubuntu 18.04.1 LTS. Working command is like `find / ! \( -path /proc -prune \) -type f -name '*.js'` - e.g. it does not traverse /proc and *does not print errors* about not entering this forbidden directory. – Nishi Nov 21 '18 at 12:53
  • Why is not this accepted answer? If I haven't scrolled past it, I would never find this, which actually solves problem – xZero Jan 10 '19 at 12:16
  • @GetFree,you said `-prune does not exclude the directory itself`,but through test in centos 7.4,your answer also `not exclude the directory itsel`.For example,`find -not -path "./.git/*" -type d` also include `./.git` – kittygirl Jan 30 '19 at 13:57
  • @kittygirl, you have to include the `-name` filter as well to search for a specific file extension. If you want to search for files and dirs alike, but want to exclude a given directory, you either use `-not -name` to exclude that directory name or `-not path` to exclude a specific directory path, e.g. `-not -path "./.git"` – GetFree Jan 30 '19 at 23:20
  • @helion3 it is likely because of the use of -o which means or, which will negate the pruning. remove the -o and it should work with prune. – mmm Nov 30 '19 at 15:10
  • Got this error on MacOS: find: illegal option -- n – Long Nguyen Apr 09 '21 at 13:33
1393

Use the -prune switch. For example, if you want to exclude the misc directory just add a -path ./misc -prune -o to your find command:

find . -path ./misc -prune -false -o -name '*.txt'

Here is an example with multiple directories:

find . -type d \( -path dir1 -o -path dir2 -o -path dir3 \) -prune -false -o -name '*.txt'

Here we exclude ./dir1, ./dir2 and ./dir3 in the current directory, since in find expressions it is an action that acts on the criteria -path dir1 -o -path dir2 -o -path dir3 (if dir1 or dir2 or dir3), ANDed with type -d.

To exclude directory name at any level, use -name:

find . -type d \( -name node_modules -o -name dir2 -o -path name \) -prune -false -o -name '*.json'
Torque
  • 2,663
  • 1
  • 25
  • 32
f10bit
  • 15,314
  • 2
  • 22
  • 20
  • 106
    Hmm. This doesn't work for me either as it will include the ignored directory "./misc" in the output. – Theuni Dec 12 '12 at 08:52
  • 96
    @Theuni It probably didn't work for you because you didn't add a `-print` (or any other action) explicitly after `-name`. In that case, both "sides" of `-o` end up printing, whereas if you use `-print`, only that side prints. – Daniel C. Sobral May 16 '13 at 19:06
  • As I explained in a comment below, I just ran both mine and GetFree's example and they return the same output: http://pastebin.com/eH4tvgSh I'm using findutils 4.4.2 and bash 4.2.045 – f10bit Sep 26 '13 at 12:39
  • 4
    From manpage: `Because -delete implies -depth, you cannot usefully use -prune and -delete together.` So, how do I go about deleting with find if I want to exclude specific directories from the deletion? – Jānis Elmeris Dec 14 '13 at 09:07
  • 29
    To remove the entire directory itself from the results use: `find . -not -path "./.git*"`. Using `./dir*` instead of `./dir/*` removes the directory as well as the contents from output. – micahblu Jul 12 '14 at 18:50
  • 2
    I found that instead of using `-o`, you can use `,` like so and avoid the need for `-print`: find . -path ./misc -prune , -name '*.txt' – Hossy Oct 18 '14 at 22:36
  • Worked great, thanks for the succinct examples. (For people having issues still, mind the spacing -- bash is picky.) – Tim S. Nov 12 '14 at 15:30
  • 1
    `-print` is not necessary if you want skip directories. Add `-not` or `!` with `-prune` also work. `find . ! \( \(-path ./dir1 -o path ./dir2 \) -prune \) -name \*.txt` – ahuigo Feb 03 '15 at 07:48
  • 3
    For those having problems with this command, try moving the -type d to after the -prune: `find . \( -path ./path1 -o -path ./path2 \) -prune -o -type d -print` – dohpaz42 Jul 30 '15 at 02:24
  • 3
    iam bit confused, what the "-o" mean? – nurulhudamustaqim Aug 30 '16 at 05:34
  • 1
    [much faster than @GetFree's solution](http://stackoverflow.com/questions/4210042/exclude-directory-from-find-command/15736463#comment68105421_15736463) but IMO a little more difficult to use – Trevor Boyd Smith Nov 04 '16 at 17:22
  • 3
    The provided command didn't work in my AWS shell, but this command did: `find . -type d \( -name dir1 -o -name dir2 -o -name dir3 \) -prune -o -type f -name "*.js" -print` – thdoan Jan 13 '17 at 04:41
  • 1
    I used to use the method described in A2, but this (A1; use of -prune etc.) is the best answer, IMO. I summarized my usage (examples) in this gist: https://gist.github.com/victoriastuart/b2f6a9b016cfe69620c1499caebbc6de – Victoria Stuart Mar 09 '17 at 18:17
  • 2
    Much faster than `--not --path` – greuze Mar 29 '17 at 14:40
  • 2
    This answer is mostly right, but the syntax could be improved for more reliable results. See https://stackoverflow.com/a/47341478 – wisbucky Nov 17 '17 at 00:41
  • 4
    @Theuni Once you prune the contents of the directory you are still matched on the directory, so you have to add a `-false` to fail the test for the directory. eg. `find . -path ./misc -prune -false -o -name '*.txt'`. – Dunes Dec 07 '17 at 12:49
  • 1
    The second part of the answer that shows excluding multiple directories is incomplete, it doesn't include the file type you are searching for – still_dreaming_1 Dec 09 '17 at 01:43
  • 1
    The semantics of `-prune` are just broken, because it prints its own path, and because it needs to be added as an `or`rule. It virtually never does what people want and seems to be an implementation artifact. To omit a directory means to omit it. Not to explicitly add it to the output. – Johannes Overmann Dec 18 '17 at 13:24
  • 125
    This question and the confusion in the answers is a manifest on how badly the find user interface matches onto what people need. – Johannes Overmann Dec 18 '17 at 13:26
  • How Can I pass an array of directories to exclude? – readytotaste Aug 19 '18 at 11:46
  • 4
    This would be clearer if you answered the question more directly, i.e. using `find . -path ./misc -prune -o -name '*.js' -print` and `find . \( -path dir1 -o -path dir2 -o -path dir3 \) -prune -o -name '*.js' -print` – wjandrea Nov 09 '18 at 14:28
  • this doesn't work for me in Ubuntu 18.04.1 LTS. Working command is like `find / ! \( -path /proc -prune \) -type f -name '*.js'` - e.g. it does not traverse /proc and *does not print errors* about not entering this forbidden directory. Check also the comment below "KEY TAKE AWAY: **"It still traverses all of the unwanted directory, though"** )". Also see excellent analysis & benchmarking by BroSlow – Nishi Nov 21 '18 at 12:56
  • The OP specifically wants only files. So add `-type f` before the "or" operator (`-o`) to remove the unwanted dir from the results: `find -path '*/ignoredirname' -prune -type f -o -name '*.js'` – Brent Faust Jan 16 '19 at 19:08
  • 4
    This is not helpful, however... I still maintain that 'find' is one of the most terrifying & powerful commands ever included in the shell environment. With commands like 'rm -rf' the ways you can accidentally mistype your command are pretty obvious and well known. The ways you can accidentally destroy data with find are confusing, numerous, and frightening. And even testing your find, intended to delete files, can be useless because depending on how you use '-delete' or '-exec' or '-print0' to feed xargs? The entire meaning of your find can change. Just... please be careful with this monster. – EricDAltman Feb 10 '19 at 01:39
  • 4
    Can someone plz rewrite this expression semantically using `AND` and `OR` (and parenthesi), just for understanding of order of logical operations. Otherwise those `-o` just confuse of the order of logical operation and what ANDs with what and at what precedence... – Dimitry K Mar 05 '19 at 14:00
  • 4
    I've been here several times over the years and this has never worked. I now realize due to comment here https://stackoverflow.com/questions/4210042/how-to-exclude-a-directory-in-find-command/16595367#16595367 that the syntax of the string after -path must match the output of what find would print if it were going to print that directory! So in my case I changed `-path .git` to `-path ./.git`. – PatS Aug 05 '19 at 17:53
  • 2
    To understand why `-print` is explicitly needed, see Suppliment and Answer sections of [this question](https://stackoverflow.com/questions/58542440/how-can-this-find-prunes-behavior-be-understood). – ynn Oct 24 '19 at 17:06
  • i dont think you should be using -o ... it means or .. so you are negating whatever you wrote to be pruned. and this answer has 1000 up votes. – mmm Nov 30 '19 at 15:09
  • 1
    @mmm: No, you need -o, or only the pruned directory will be matched, which is the opposite of what you want. Did you even try it? – Nick Matteo Mar 30 '20 at 02:20
  • Can I also apply this into sub-folders for specific foder names? @f10bit – alper Apr 08 '20 at 11:40
  • 1
    For excluding multiple directories, this worked for me: `find . -path ./dir1 -prune -o -path ./dir2 -prune -o -path ./dir3 -prune -o -name '*.txt' -print` Note that globbing works with this pattern. So lets say you wanted to exclude all directories starting with "dir" and also exclude a directory called "folder1"; you could do it like this: `find . -path ./dir* -prune -o -path ./folder1 -prune -o -name '*.txt' -print` – Shai Apr 29 '20 at 16:03
  • @ahuigo great comment, but you made syntax errors which ruin it: 1. there should be a space after the second \( 2. the second path option misses it's hyphen. – Attila Csipak Aug 12 '20 at 15:53
  • 1
    Like in this answer, watch for the proper use of brackets, otherwise -o will not be applied onto the proper operands. – Fabien Haddadi Aug 28 '20 at 23:19
  • 1
    You can leave the `false` parameter which then just shows the excluded `dir` without crawling. – Timo Oct 14 '20 at 17:59
  • 10
    I've been struggling to understand the `-false` flag. Now I think I get it. In this example, we can use either the `-false` flag on the left hand side of `-o`, OR the `-print` on the right hand side of `-o`. The purpose is to skip printing the name of the excluded dir. Since either method will suppress the printing, we don't have to supply both flags -- although that wouldn't hurt, either. P.S., [Johannes Overmann](https://stackoverflow.com/users/2205033/johannes-overmann) is so right. I've been a heavy user of UNIX for decades, but still haven't gotten the hang of `find`. Maybe never will. – Vincent Yin Dec 02 '20 at 20:41
  • ./find_generated.sh: line 1: /usr/bin/find: Argument list too long :( crashed, when dealing with 15537 dirs of exclusion. Is there some other way? – Pradeep Singh Dec 11 '20 at 11:42
  • 1
    @JohannesOvermann thank you. I've been going a little crazy trying to understand the `-false` flag too. I'm glad (a) I'm not alone and (b) our understandings match haha – DanZimm Dec 18 '20 at 12:21
  • On my system (debian 10) if I supply only `-false` before the `-o`, it prints the excluded directories too. if I supply `-false` before `-o` and `-print` after `-o`, it again prints everything. *Only* if I supply no `-false` at all and then `-print` after the `-o` I get the desired result... – confetti Jan 02 '21 at 07:01
  • 3
    the `-false` flag does not exist in alpine (busybox) – glen Feb 03 '21 at 10:56
514

I find the following easier to reason about than other proposed solutions:

find build -not \( -path build/external -prune \) -name \*.js
# you can also exclude multiple paths
find build -not \( -path build/external -prune \) -not \( -path build/blog -prune \) -name \*.js

Important Note: the paths you type after -path must exactly match what find would print without the exclusion. If this sentence confuses you just make sure to use full paths through out the whole command like this: find /full/path/ -not \( -path /full/path/exclude/this -prune \) .... See note [1] if you'd like a better understanding.

Inside \( and \) is an expression that will match exactly build/external (see important note above), and will, on success, avoid traversing anything below. This is then grouped as a single expression with the escaped parenthesis, and prefixed with -not which will make find skip anything that was matched by that expression.

One might ask if adding -not will not make all other files hidden by -prune reappear, and the answer is no. The way -prune works is that anything that, once it is reached, the files below that directory are permanently ignored.

This comes from an actual use case, where I needed to call yui-compressor on some files generated by wintersmith, but leave out other files that need to be sent as-is.


Note [1]: If you want to exclude /tmp/foo/bar and you run find like this "find /tmp \(..." then you must specify -path /tmp/foo/bar. If on the other hand you run find like this cd /tmp; find . \(... then you must specify -path ./foo/bar.

Konrad Rudolph
  • 482,603
  • 120
  • 884
  • 1,141
Daniel C. Sobral
  • 284,820
  • 82
  • 479
  • 670
  • 42
    Outstanding answer, thank you. This works and is scalable (readable) for multiple exclusions. You are a gentlemen and a scholar sir. Thank you for the example for multiple exclusions – Freedom_Ben Aug 16 '13 at 16:38
  • 8
    This does not work if I want to use -delete switch: `find . -not \( -path ./CVS -prune \) -type f -mtime +100 -delete find: The -delete action atomatically turns on -depth, but -prune does nothing when -depth is in effect. If you want to carry on anyway, just explicitly use the -depth option.` – Jānis Elmeris Dec 14 '13 at 09:12
  • 18
    @Janis You can use `-exec rm -rf {} \;` instead of `-delete`. – Daniel C. Sobral Dec 15 '13 at 21:14
  • @DanielC.Sobral Thanks for the tip! – Jānis Elmeris Dec 18 '13 at 14:49
  • 1
    This is great and worked perfectly for excluding huge static directories from my bytecode search. One gotcha: the -name parameter has to be after the -not (-prune) command for the exclusion to work. – Matthew F. Robben Jan 04 '14 at 21:10
  • 13
    By examining the output of `find`, this is obvious really, but it tripped me up. If you are searching in the current directory (by specifying `.` as the search path, or not specifying one at all), you most likely want your pattern after `-path` to start with `./`, e.g: `find -not \( -path ./.git -prune \) -type f`. – Zantier Oct 09 '14 at 10:10
  • Windows git bash shell find does not seem to support this but if you have cygwin you can do something like `/c/cygwin/bin/find` it spits some errors, probably without symlinking stuff over to git bash but seems to work for this task. – sabgenton Feb 25 '15 at 03:26
  • @sabgenton it works for me in git bash 1.9.5. See my answer on [how to exclude `.git` and `node_modules`](http://stackoverflow.com/q/34152804/245966) from being traversed. – jakub.g Dec 08 '15 at 09:57
  • @sabgenton Well in fact it seems this indeed does not work with `-name` part. But this is the easy part: you can exclude stuff using this answer, and then pipe to grep. – jakub.g Dec 08 '15 at 10:11
  • 1
    Instead of using the `-not` switch, why don't you simply separate the two statements with a comma? Like `find build -path build/external -prune , -name *.js` – M.Herzkamp Feb 08 '16 at 02:38
  • @M.Herzkamp Comma is not on BSD. – Daniel C. Sobral Feb 09 '16 at 07:16
  • I like that this approach makes the exclusion code self-contained (i.e. not split before/after the other find primaries). That enabled me to write a short-hand script, ~/bin/exclude, so I could say `$ find . \`exclude .git CVS\` -name foo`. Script is: `for k in "$@" ; do echo -not \( -type d -name "${k%/}" -prune \) ; done` – Noach Magedman Mar 30 '16 at 11:14
  • Works for me in Win7, using gfind from gow. Here is my exact syntax with the cmd.exe shell (i.e. not bash): gfind . -not ( -path ./DrU -prune ) -not ( -path ./DrV -prune ) – Radim Cernej May 19 '16 at 22:42
  • 2
    @Janis from the manpage: `-prune True; if the file is a directory, do not descend into it. If -depth is given, false; no effect. Because -delete implies -depth, you cannot usefully use -prune and -delete together.` – sjas Aug 01 '16 at 10:18
  • 10
    A more precise (and POSIX compatible) variation of this method: `find searchdir \! \( -type d \( -path './excludedir/*' -o -path './excludedir2/*' -o -path './excludedir3/*' \) -prune \)` followed by any conditions that should match what you are looking for. – Walf May 26 '17 at 04:17
  • 1
    Do not omit the spaces after \\( and before \\) :-) – bebbo Jan 08 '18 at 07:47
  • 1
    Perhaps you could add some clarification in that the `-prune` is looking for the actual text the find output displays; in your example `build/external`. Another example is a more common `find .`, in which case the `./` needs to lead the prune'd expression. – Chris K Feb 16 '18 at 18:40
  • 2
    My suggested command's general format should actually be `find searchdir \! \( -type d \( -path 'searchdir/excludedir' -o -path 'searchdir/exclude/dir/2' -o -path 'searchdir/exclude/dir3' \) -prune \) ...` – Walf May 14 '18 at 01:59
  • 1
    only workable answer because it omits the -o option. jeezus. – mmm Nov 30 '19 at 15:11
  • !!! Make sure `-type f` is behind `-not \( -path ./build/external -prune \)` otherwise you will have a bad day !!! – qräbnö Feb 01 '21 at 16:20
  • This is a great answer. I always end up crafting some pipe train because I can never remember the right order of find expressions to exclude more than one directory. This is the most straight forward solution and is really pretty easy to remember. Thank you Daniel! – MrJman006 Apr 25 '21 at 18:03
237

There is clearly some confusion here as to what the preferred syntax for skipping a directory should be.

GNU Opinion

To ignore a directory and the files under it, use -prune

From the GNU find man page

Reasoning

-prune stops find from descending into a directory. Just specifying -not -path will still descend into the skipped directory, but -not -path will be false whenever find tests each file.

Issues with -prune

-prune does what it's intended to, but are still some things you have to take care of when using it.

  1. find prints the pruned directory.

    • TRUE That's intended behavior, it just doesn't descend into it. To avoid printing the directory altogether, use a syntax that logically omits it.
  2. -prune only works with -print and no other actions.

    • NOT TRUE. -prune works with any action except -delete. Why doesn't it work with delete? For -delete to work, find needs to traverse the directory in DFS order, since -deletewill first delete the leaves, then the parents of the leaves, etc... But for specifying -prune to make sense, find needs to hit a directory and stop descending it, which clearly makes no sense with -depth or -delete on.

Performance

I set up a simple test of the three top upvoted answers on this question (replaced -print with -exec bash -c 'echo $0' {} \; to show another action example). Results are below

----------------------------------------------
# of files/dirs in level one directories
.performance_test/prune_me     702702    
.performance_test/other        2         
----------------------------------------------

> find ".performance_test" -path ".performance_test/prune_me" -prune -o -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
  [# of files] 3 [Runtime(ns)] 23513814

> find ".performance_test" -not \( -path ".performance_test/prune_me" -prune \) -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
  [# of files] 3 [Runtime(ns)] 10670141

> find ".performance_test" -not -path ".performance_test/prune_me*" -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
  [# of files] 3 [Runtime(ns)] 864843145

Conclusion

Both f10bit's syntax and Daniel C. Sobral's syntax took 10-25ms to run on average. GetFree's syntax, which doesn't use -prune, took 865ms. So, yes this is a rather extreme example, but if you care about run time and are doing anything remotely intensive you should use -prune.

Note Daniel C. Sobral's syntax performed the better of the two -prune syntaxes; but, I strongly suspect this is the result of some caching as switching the order in which the two ran resulted in the opposite result, while the non-prune version was always slowest.

Test Script

#!/bin/bash

dir='.performance_test'

setup() {
  mkdir "$dir" || exit 1
  mkdir -p "$dir/prune_me/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/w/x/y/z" \
    "$dir/other"

  find "$dir/prune_me" -depth -type d -exec mkdir '{}'/{A..Z} \;
  find "$dir/prune_me" -type d -exec touch '{}'/{1..1000} \;
  touch "$dir/other/foo"
}

cleanup() {
  rm -rf "$dir"
}

stats() {
  for file in "$dir"/*; do
    if [[ -d "$file" ]]; then
      count=$(find "$file" | wc -l)
      printf "%-30s %-10s\n" "$file" "$count"
    fi
  done
}

name1() {
  find "$dir" -path "$dir/prune_me" -prune -o -exec bash -c 'echo "$0"'  {} \;
}

name2() {
  find "$dir" -not \( -path "$dir/prune_me" -prune \) -exec bash -c 'echo "$0"' {} \;
}

name3() {
  find "$dir" -not -path "$dir/prune_me*" -exec bash -c 'echo "$0"' {} \;
}

printf "Setting up test files...\n\n"
setup
echo "----------------------------------------------"
echo "# of files/dirs in level one directories"
stats | sort -k 2 -n -r
echo "----------------------------------------------"

printf "\nRunning performance test...\n\n"

echo \> find \""$dir"\" -path \""$dir/prune_me"\" -prune -o -exec bash -c \'echo \"\$0\"\'  {} \\\;
name1
s=$(date +%s%N)
name1_num=$(name1 | wc -l)
e=$(date +%s%N)
name1_perf=$((e-s))
printf "  [# of files] $name1_num [Runtime(ns)] $name1_perf\n\n"

echo \> find \""$dir"\" -not \\\( -path \""$dir/prune_me"\" -prune \\\) -exec bash -c \'echo \"\$0\"\' {} \\\;
name2
s=$(date +%s%N)
name2_num=$(name2 | wc -l)
e=$(date +%s%N)
name2_perf=$((e-s))
printf "  [# of files] $name2_num [Runtime(ns)] $name2_perf\n\n"

echo \> find \""$dir"\" -not -path \""$dir/prune_me*"\" -exec bash -c \'echo \"\$0\"\' {} \\\;
name3
s=$(date +%s%N)
name3_num=$(name3 | wc -l)
e=$(date +%s%N)
name3_perf=$((e-s))
printf "  [# of files] $name3_num [Runtime(ns)] $name3_perf\n\n"

echo "Cleaning up test files..."
cleanup
Community
  • 1
  • 1
Reinstate Monica Please
  • 9,979
  • 2
  • 25
  • 44
  • 19
    Thank you for a very good analysis. Regarding "I strongly suspect this is the result of some caching" you can run this command: sudo sh -c "free && sync && echo 3 > /proc/sys/vm/drop_caches && free" to clear the cache (see http://unix.stackexchange.com/questions/87908/how-do-you-empty-the-buffers-and-cache-on-a-linux-system). – ndemou Nov 19 '14 at 09:40
  • After few tests on those two with `-prune` I can tell there is rarely any difference. Do keep in mind that which command start first will benefit from cpu performance, the later **cpu warm up > performance drop** cause minor slow down (I did purge cache before each command as @ndemou suggestion) – Huy.PhamNhu Sep 28 '17 at 17:35
  • Try switch number among `name1() name2() name3()` in @BroSlow test script above to change execute order to get a visual about what I said. In real life, it is unnoticeable between those two though. – Huy.PhamNhu Sep 28 '17 at 17:47
  • Applause. Thank you for this quality answer. – Stphane Jan 19 '18 at 13:53
  • You should not be -o which means or. so you are pruning in the first step and then forgetting all about it in the next. – mmm Nov 30 '19 at 15:12
159

This is the only one that worked for me.

find / -name MyFile ! -path '*/Directory/*'

Searching for "MyFile" excluding "Directory". Give emphasis to the stars * .

DimiDak
  • 2,990
  • 1
  • 16
  • 23
66

One option would be to exclude all results that contain the directory name with grep. For example:

find . -name '*.js' | grep -v excludeddir
Joshua
  • 4,940
  • 1
  • 23
  • 39
  • 53
    This will make your search very slow – Dorian Feb 19 '13 at 12:01
  • 6
    This one worked for me, others (which use `-prune`) - doesn't. – Andron Mar 28 '13 at 11:03
  • 7
    Slow in large results, but useful in smaller sets. But how to exclude multiple directories using grep? Of course this way: `find . -name '*.js' | grep -v excludeddir | grep -v excludedir2 | grep -v excludedir3` but there may be some one grep way. – Timo Kähkönen May 01 '13 at 09:47
  • +1 because this gave me the idea to use grep to add color to find. – Nick Mar 12 '14 at 13:22
  • Where exactly would I add the `-exec` to execute something on found files? I'm looking for something like this where I can exclude paths based on regexp and grep seems to be nice but don't know how to pipe this to tar. – HMR May 24 '14 at 00:35
  • 6
    If you want to perform multiple greps then you would be better off writing it as regular expressions: `egrep -v '(dir1|dir2|dir3)'`. However, in this specific case study, it would be better to exclude directories within `find` itself. – Laurence Nov 10 '14 at 09:58
  • 1
    yes, and you don't need parentheses and it would be better to use ^ to ensure it matches directoryname at the start of the string eg: find . -name '*.js' | egrep -v "^\./excludeddir1|^\./excludeddir2" – Sofija Sep 03 '15 at 11:14
  • 1
    This is good because it lets you exclude items from a top level search, e.g. a directory search with `-maxdepth 1` – M1ke Sep 03 '15 at 11:21
  • true, and just noticed, ^ is enough first time, eg this regex will do same and is simpler "^\./excludeddir1|\./excludeddir2" ... might make a difference for lots of top level search to exclude – Sofija Sep 03 '15 at 11:30
  • Why dip into egrep with a nasty regex when `grep -ve dir1 -edir2 -edir3` works just as well (and is probably faster)? – CSTobey Aug 23 '16 at 15:13
  • This is also useful if you want to exclude a directory that appears at multiple levels within your hierarchy e.g. `grep -v build` – j b Feb 01 '19 at 10:25
  • This is the *only* solution that helped me find all `package.json` files that weren't inside of a `node_modules` folder. `find . -name 'package.json' | grep -v node_modules` – anon58192932 Jun 05 '19 at 17:08
  • I've been here several times over the years and this has never worked. I now realize due to comment here https://stackoverflow.com/a/16595367/3281336 that I needed to change `-path node_modules` to `-path ./node_modules`. The syntax of the string after -path must match the output of what find would print if it were going to print that directory! – PatS Aug 05 '19 at 17:52
  • Won't work if reading the excluded directory causes an error that terminates `find`. Also extremely inefficient. – ivan_pozdeev Dec 18 '19 at 19:38
  • 1
    re *This will make your search very slow* Maybe, but at least it works. The whole efficiency thing is somewhat besides the point if you are typing on the terminal and reasonably deep in the file hierarchy, i.e. not at `/` or `~`. If this is being executed repeatedly within a program, then sure, messing around with `prune` (who pretty much no proponent here bothered to explain the syntax of) is better. – JL Peyret Jun 18 '20 at 19:08
  • Seconding JL Peyret- this *may* be slow but it *just works*. Compare to all the issues people had with the -prune and -not -path answers. When I want to do a search quickly at the command line (the usual case), this is the first thing to try. If writing a script that has to be fast, maybe not. – ttulinsky Aug 03 '20 at 05:34
42

I prefer the -not notation ... it's more readable:

find . -name '*.js' -and -not -path directory
mpapis
  • 51,279
  • 14
  • 117
  • 159
  • 6
    Sorry, it doesn't work. The man page for `find` says: "To ignore a directory and the files under it, use -prune". – Christian Davén Aug 25 '12 at 20:25
  • 9
    This is wrong. It doesn't prevent find from entering the directory and traversing all the files inside. – GetFree Apr 01 '13 at 01:37
  • `find . -iname '*' -and -not -path './somePath'` doesn't prevent it from entering said directory. – Lemmings19 May 30 '13 at 00:00
  • This helped me with .git path `find . -iname '*' -not -path './.git/*'` – Mark Shust at M.academy Sep 27 '13 at 20:01
  • 8
    @rane: More specifically `find . -not -path "*/.git*"` would be what you want. – Ben Nov 28 '13 at 17:50
  • I used find * and it didn't list hidden directories like .git. Might be what you're looking for – justin Mar 16 '14 at 12:05
  • @GetFree: There never was a requirement to /not/ descend into the directory. I'll give you that this is less efficient. – Brian Apr 21 '15 at 16:02
  • This is great! I used it to delete `data/*` sub-dirs except for the top-level directory 'data', leaving `data/*` files in place (this handles deleting unpacked zip/tgz archives, without deleting the archives themselves). `find ./data -type d -and -not -regex "^./data$" -prune -exec rm -rf {} \;` – stason Oct 17 '18 at 02:54
29

Use the -prune option. So, something like:

find . -type d -name proc -prune -o -name '*.js'

The '-type d -name proc -prune' only look for directories named proc to exclude.
The '-o' is an 'OR' operator.

Drew Frezell
  • 2,334
  • 19
  • 12
  • 3
    This is the only pure-"find" solution that worked for me. The directories I wished to exclude are NOT immediately below the current working directory. – Lambart Apr 15 '13 at 23:06
  • 6
    However, adding `-print` to the end may improve results. `find . -type d -name .hg -prune -o -name data` ignored the contents of the (multiple) `.hg` directories, but listed the `.hg` directories themselves. With `-print`, it only listed the "data" directories I was seeking. – Lambart Nov 04 '13 at 19:39
  • yeah, significantly better explained than the accepted answer. and it works. Here's a flavor that finds markdowns, except those under `/node_modules/` : `find . -name node_modules -prune -o -name '*.md'` Nothing wrong with wanting to add extra stuff like -print, but at least lets have something basic that works first. – JL Peyret Jun 18 '20 at 19:14
24

-prune definitely works and is the best answer because it prevents descending into the dir that you want to exclude. -not -path which still searches the excluded dir, it just doesn't print the result, which could be an issue if the excluded dir is mounted network volume or you don't permissions.

The tricky part is that find is very particular about the order of the arguments, so if you don't get them just right, your command may not work. The order of arguments is generally as such:

find {path} {options} {action}

{path}: Put all the path related arguments first, like . -path './dir1' -prune -o

{options}: I have the most success when putting -name, -iname, etc as the last option in this group. E.g. -type f -iname '*.js'

{action}: You'll want to add -print when using -prune

Here's a working example:

# setup test
mkdir dir1 dir2 dir3
touch dir1/file.txt; touch dir1/file.js
touch dir2/file.txt; touch dir2/file.js
touch dir3/file.txt; touch dir3/file.js

# search for *.js, exclude dir1
find . -path './dir1' -prune -o -type f -iname '*.js' -print

# search for *.js, exclude dir1 and dir2
find . \( -path './dir1' -o -path './dir2' \) -prune -o -type f -iname '*.js' -print
wisbucky
  • 22,510
  • 8
  • 103
  • 76
17

This is the format I used to exclude some paths:

$ find ./ -type f -name "pattern" ! -path "excluded path" ! -path "excluded path"

I used this to find all files not in ".*" paths:

$ find ./ -type f -name "*" ! -path "./.*" ! -path "./*/.*"
user1882879
  • 205
  • 2
  • 5
  • 1
    I tried this and it still descends into the directories, so speed is definitely not improved. – Br.Bill Aug 29 '18 at 18:37
15

The -path -prune approach also works with wildcards in the path. Here is a find statement that will find the directories for a git server serving multiple git repositiories leaving out the git internal directories:

find . -type d \
   -not \( -path */objects -prune \) \
   -not \( -path */branches -prune \) \
   -not \( -path */refs -prune \) \
   -not \( -path */logs -prune \) \
   -not \( -path */.git -prune \) \
   -not \( -path */info -prune \) \
   -not \( -path */hooks -prune \)  
Wolfgang Fahl
  • 12,097
  • 9
  • 75
  • 150
15

There are plenty of good answers, it just took me some time to understand what each element of the command was for and the logic behind it.

find . -path ./misc -prune -o -name '*.txt' -print

find will start finding files and directories in the current directory, hence the find ..

The -o option stands for a logical OR and separates the two parts of the command :

[ -path ./misc -prune ] OR [ -name '*.txt' -print ]

Any directory or file that is not the ./misc directory will not pass the first test -path ./misc. But they will be tested against the second expression. If their name corresponds to the pattern *.txt they get printed, because of the -print option.

When find reaches the ./misc directory, this directory only satisfies the first expression. So the -prune option will be applied to it. It tells the find command to not explore that directory. So any file or directory in ./misc will not even be explored by find, will not be tested against the second part of the expression and will not be printed.

Istopopoki
  • 1,301
  • 9
  • 18
  • 4
    Everyone's got a solution but yours explained it the best. I was adamant to have -name be used first rather than -path. Your explanation was adequate to arrive at what I wanted. find . -name "*.txt" -print -o -path ./misc -prune – Vendetta V Apr 24 '20 at 17:27
10

To exclude multiple directories:

find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" \)

To add directories, add -o -path "./dirname/*":

find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" -o -path "./dir3/*"\)

But maybe you should use a regular expression, if there are many directories to exclude.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
JBENOIT
  • 381
  • 2
  • 14
9

a good trick for avoiding printing the pruned directories is to use -print (works for -exec as well) after the right side of the -or after -prune. For example, ...

find . -path "*/.*" -prune -or -iname "*.j2"

will print the path of all files beneath the current directory with the `.j2" extension, skipping all hidden directories. Neat. But it will also print the print the full path of each directory one is skipping, as noted above. However, the following does not, ...

find . -path "*/.*" -prune -or -iname "*.j2" -print

because logically there's a hidden -and after the -iname operator and before the -print. This binds it to the right part of the -or clause due to boolean order of operations and associativity. But the docs say there's a hidden -print if it (or any of its cousins ... -print0, etc) is not specified. So why isn't the left part of the -or printing? Apparently (and I didn't understand this from my first reading the man page), that is true if there there is no -print -or -exec ANYWHERE, in which case, -print is logically sprinkled around such that everything gets printed. If even ONE print-style operation is expressed in any clause, all those hidden logical ones go away and you get only what you specify. Now frankly, I might have preferred it the other way around, but then a find with only descriptive operators would apparently do nothing, so I guess it makes sense as it is. As mentioned above, this all works with -exec as well, so the following gives a full ls -la listing for each file with the desired extension, but not listing the first level of each hidden directory, ...

find . -path "*/.*" -prune -or -iname "*.j2" -exec ls -la -- {} +

For me (and others on this thread), find syntax gets pretty baroque pretty quickly, so I always throw in parens to make SURE I know what binds to what, so I usually create a macro for type-ability and form all such statements as ...

find . \( \( ... description of stuff to avoid ... \) -prune \) -or \
\( ... description of stuff I want to find ... [ -exec or -print] \)

It's hard to go wrong by setting up the world into two parts this way. I hope this helps, though it seems unlikely for anyone to read down to the 30+th answer and vote it up, but one can hope. :-)

cycollins
  • 315
  • 3
  • 9
8

For a working solution (tested on Ubuntu 12.04 (Precise Pangolin))...

find ! -path "dir1" -iname "*.mp3"

will search for MP3 files in the current folder and subfolders except in dir1 subfolder.

Use:

find ! -path "dir1" ! -path "dir2" -iname "*.mp3"

...to exclude dir1 AND dir2

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
james dupin
  • 81
  • 1
  • 1
6

You can also use regular expressions to include / exclude some files /dirs your search using something like this:

find . -regextype posix-egrep -regex ".*\.(js|vue|s?css|php|html|json)$" -and -not -regex ".*/(node_modules|vendor)/.*" 

This will only give you all js, vue, css, etc files but excluding all files in the node_modules and vendor folders.

supersan
  • 4,328
  • 1
  • 34
  • 51
5
find -name '*.js' -not -path './node_modules/*' -not -path './vendor/*'

seems to work the same as

find -name '*.js' -not \( -path './node_modules/*' -o -path './vendor/*' \)

and is easier to remember IMO.

Funkodebat
  • 5,229
  • 3
  • 36
  • 54
5

You can use the prune option to achieve this. As in for example:

find ./ -path ./beta/* -prune -o -iname example.com -print

Or the inverse grep “grep -v” option:

find -iname example.com | grep -v beta

You can find detailed instructions and examples in Linux find command exclude directories from searching.

Siju V
  • 133
  • 1
  • 5
  • The grep solution is the only one that excludes all directories by the same name. When trying to exclude "node_modules" that is quite useful. – bmacnaughton May 08 '17 at 03:40
  • 3
    @bmacnaughton - not true! I came here specifically looking to exclude "node_modules" and after reading many fine answers I settled on `find . -type f -print -o -path "*/node_modules" -prune` ... using the wildcard this skips "node_modules" at any level; using `-print` on the first alternative `-type f -print` makes only that part print, so the "node_modules" directories themselves are not listed. (it can also be reversed: `find . -path "*/node_modules" -prune -o -type f -print`) – Stephen P Feb 22 '18 at 20:34
  • what is */ doing there. What is the exact file you want to exclude.Are ypu using it as wildcard? – Siju V Feb 23 '18 at 00:37
  • 1
    @StephenP, thanks for pointing this out; I learned the difference between using `./node_modules` and `*/node_modules` from it. For my case, where `node_modules` only exists in the the directory I start the search in (and under that `node_modules` directory), I can use `find . -type f -print -o -path "./node_modules" -prune` because there won't be a `node_modules` directory under any other directory. – bmacnaughton Feb 25 '18 at 15:31
  • 1
    @SijuV - in the directory where I was searching there was a `node_modules` subdirectory, but there were also subdirectories that had their own _node_modules_ ... using `./node_modules` matches only the subdirectory `node_modules` under the current directory `.` and prunes it; using `*/node_modules` matches and prunes the directory at any depth, because the `*` as a [glob](http://tldp.org/LDP/abs/html/globbingref.html) matches any leading path prefix, such as `./test5/main/node_modules`, not only the `./` prefix. The `*` is a wildcard, but as a glob not as a regex. – Stephen P Feb 26 '18 at 17:53
  • If this is a project using git, you might just do `git ls-files |grep "*.js"`, since presumably the .gitignore file specifies which files you usually want to ignore (like `node_modules`) and `git ls-files` shows all project files (ignoring those in `.gitignore`). – Peter W Jun 22 '18 at 00:23
5

TLDR: understand your root directories and tailor your search from there, using the -path <excluded_path> -prune -o option. Do not include a trailing / at the end of the excluded path.

Example:

find / -path /mnt -prune -o -name "*libname-server-2.a*" -print


To effectively use the find I believe that it is imperative to have a good understanding of your file system directory structure. On my home computer I have multi-TB hard drives, with about half of that content backed up using rsnapshot (i.e., rsync). Although backing up to to a physically independent (duplicate) drive, it is mounted under my system root (/) directory: /mnt/Backups/rsnapshot_backups/:

/mnt/Backups/
└── rsnapshot_backups/
    ├── hourly.0/
    ├── hourly.1/
    ├── ...
    ├── daily.0/
    ├── daily.1/
    ├── ...
    ├── weekly.0/
    ├── weekly.1/
    ├── ...
    ├── monthly.0/
    ├── monthly.1/
    └── ...

The /mnt/Backups/rsnapshot_backups/ directory currently occupies ~2.9 TB, with ~60M files and folders; simply traversing those contents takes time:

## As sudo (#), to avoid numerous "Permission denied" warnings:

time find /mnt/Backups/rsnapshot_backups | wc -l
60314138    ## 60.3M files, folders
34:07.30    ## 34 min

time du /mnt/Backups/rsnapshot_backups -d 0
3112240160  /mnt/Backups/rsnapshot_backups    ## 3.1 TB
33:51.88    ## 34 min

time rsnapshot du    ## << more accurate re: rsnapshot footprint
2.9T    /mnt/Backups/rsnapshot_backups/hourly.0/
4.1G    /mnt/Backups/rsnapshot_backups/hourly.1/
...
4.7G    /mnt/Backups/rsnapshot_backups/weekly.3/
2.9T    total    ## 2.9 TB, per sudo rsnapshot du (more accurate)
2:34:54          ## 2 hr 35 min

Thus, anytime I need to search for a file on my / (root) partition, I need to deal with (avoid if possible) traversing my backups partition.


EXAMPLES

Among the approached variously suggested in this thread (How to exclude a directory in find . command), I find that searches using the accepted answer are much faster -- with caveats.

Solution 1

Let's say I want to find the system file libname-server-2.a, but I do not want to search through my rsnapshot backups. To quickly find a system file, use the exclude path /mnt (i.e., use /mnt, not /mnt/, or /mnt/Backups, or ...):

## As sudo (#), to avoid numerous "Permission denied" warnings:

time find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
/usr/lib/libname-server-2.a
real    0m8.644s              ## 8.6 sec  <<< NOTE!
user    0m1.669s
 sys    0m2.466s

## As regular user (victoria); I also use an alternate timing mechanism, as
## here I am using 2>/dev/null to suppress "Permission denied" warnings:

$ START="$(date +"%s")" && find 2>/dev/null / -path /mnt -prune -o \
    -name "*libname-server-2.a*" -print; END="$(date +"%s")"; \
    TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/usr/lib/libname-server-2.a
find command took 3 sec     ## ~3 sec  <<< NOTE!

... finds that file in just a few seconds, while this take much longer (appearing to recurse through all of the "excluded" directories):

## As sudo (#), to avoid numerous "Permission denied" warnings:

time find / -path /mnt/ -prune -o -name "*libname-server-2.a*" -print
find: warning: -path /mnt/ will not match anything because it ends with /.
/usr/lib/libname-server-2.a
real    33m10.658s            ## 33 min 11 sec (~231-663x slower!)
user    1m43.142s
 sys    2m22.666s

## As regular user (victoria); I also use an alternate timing mechanism, as
## here I am using 2>/dev/null to suppress "Permission denied" warnings:

$ START="$(date +"%s")" && find 2>/dev/null / -path /mnt/ -prune -o \
    -name "*libname-server-2.a*" -print; END="$(date +"%s")"; \
    TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/usr/lib/libname-server-2.a
find command took 1775 sec    ## 29.6 min

Solution 2

The other solution offered in this thread (SO#4210042) also performs poorly:

## As sudo (#), to avoid numerous "Permission denied" warnings:

time find / -name "*libname-server-2.a*" -not -path "/mnt"
/usr/lib/libname-server-2.a
real    33m37.911s            ## 33 min 38 sec (~235x slower)
user    1m45.134s
 sys    2m31.846s

time find / -name "*libname-server-2.a*" -not -path "/mnt/*"
/usr/lib/libname-server-2.a
real    33m11.208s            ## 33 min 11 sec
user    1m22.185s
 sys    2m29.962s

SUMMARY | CONCLUSIONS

Use the approach illustrated in "Solution 1"

find / -path /mnt -prune -o -name "*libname-server-2.a*" -print

i.e.

... -path <excluded_path> -prune -o ...

noting that whenever you add the trailing / to the excluded path, the find command then recursively enters (all those) /mnt/* directories -- which in my case, because of the /mnt/Backups/rsnapshot_backups/* subdirectories, additionally includes ~2.9 TB of files to search! By not appending a trailing / the search should complete almost immediately (within seconds).

"Solution 2" (... -not -path <exclude path> ...) likewise appears to recursively search through the excluded directories -- not returning excluded matches, but unnecessarily consuming that search time.


Searching within those rsnapshot backups:

To find a file in one of my hourly/daily/weekly/monthly rsnapshot backups):

$ START="$(date +"%s")" && find 2>/dev/null /mnt/Backups/rsnapshot_backups/daily.0 -name '*04t8ugijrlkj.jpg'; END="$(date +"%s")"; TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/mnt/Backups/rsnapshot_backups/daily.0/snapshot_root/mnt/Vancouver/temp/04t8ugijrlkj.jpg
find command took 312 sec   ## 5.2 minutes: despite apparent rsnapshot size
                            ## (~4 GB), it is in fact searching through ~2.9 TB)

Excluding a nested directory:

Here, I want to exclude a nested directory, e.g. /mnt/Vancouver/projects/ie/claws/data/* when searching from /mnt/Vancouver/projects/:

$ time find . -iname '*test_file*'
./ie/claws/data/test_file
./ie/claws/test_file
0:01.97

$ time find . -path '*/data' -prune -o -iname '*test_file*' -print
./ie/claws/test_file
0:00.07

Aside: Adding -print at the end of the command suppresses the printout of the excluded directory:

$ find / -path /mnt -prune -o -name "*libname-server-2.a*"
/mnt
/usr/lib/libname-server-2.a

$ find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
/usr/lib/libname-server-2.a
Victoria Stuart
  • 3,146
  • 2
  • 28
  • 26
  • It's not the size of the files that slows `find`, it's the *number of directory entries* it must examine. So it's much worse if you have many, many small files (especially if they are all multiply linked!) than if you just have a handful of multi-gigabyte files. – Toby Speight Oct 02 '18 at 09:44
  • @TobySpeight: good point. I mentioned the search space size to indicate scale, which also contains many files. A quick search of root (/) with `sudo ls -R / | wc -l` indicates ~76.5M files (most of which are backed up except "non-config" system files); `/mnt/Vancouver/` with `ls -R | wc -l` indicates ~2.35M files; `/home/victoria/` contains 0.668M files. – Victoria Stuart Oct 02 '18 at 15:51
5
find . \( -path '.**/.git' -o -path '.**/.hg' \) -prune -o -name '*.js' -print

The example above finds all *.js files under the current directory, excluding folders .git and .hg, does not matter how deep these .git and .hg folders are.

Note: this also works:

find . \( -path '.*/.git' -o -path '.*/.hg' \) -prune -o -name '*.js' -print

but I prefer the ** notation for consistency with some other tools which would be off topic here.

Richard Gomes
  • 4,672
  • 1
  • 33
  • 45
4

None of previous answers is good on Ubuntu. Try this:

find . ! -path "*/test/*" -type f -name "*.js" ! -name "*-min-*" ! -name "*console*"

I have found this here

Community
  • 1
  • 1
Sixro
  • 327
  • 2
  • 11
  • I don't see any reason why any of the answers with more than 100 points shouldn't work on Ubuntu. – Axel Beckert Sep 02 '15 at 00:10
  • find is everywhere the same implementation on all Linux distributions — the one from the GNU Project. The only difference might be the versions. But the changes in the past decade were not that invasive, except maybe for permission matching. – Axel Beckert Apr 03 '20 at 09:21
4

This is suitable for me on a Mac:

find . -name *.php -or -path "./vendor" -prune -or -path "./app/cache" -prune

It will exclude vendor and app/cache dir for search name which suffixed with php.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
jiahut
  • 1,297
  • 12
  • 13
4
find . -name '*.js' -\! -name 'glob-for-excluded-dir' -prune
Dima Lituiev
  • 10,690
  • 7
  • 32
  • 47
The Archetypal Paul
  • 39,479
  • 18
  • 96
  • 128
  • 1
    Can't get this one to work. `find ~/Projects -name '*.js' -\! -name 'node_modules' -prune` is still turning up files with `node_modules` in their path – mpen May 02 '17 at 16:17
  • 3
    @mpen , From https://stackoverflow.com/questions/4210042/how-to-exclude-a-directory-in-find-command/16595367#16595367, I learned that the syntax you want is `find ~/Projects -path ~/Projects/node_modules -prune -o -name '*.js' -print`. The name of that path must match exactly what find would print if it were going to print the directory. – PatS Aug 05 '19 at 18:00
3

I was using find to provide a list of files for xgettext, and wanted to omit a specific directory and its contents. I tried many permutations of -path combined with -prune but was unable to fully exclude the directory which I wanted gone.

Although I was able to ignore the contents of the directory which I wanted ignored, find then returned the directory itself as one of the results, which caused xgettext to crash as a result (doesn't accept directories; only files).

My solution was to simply use grep -v to skip the directory that I didn't want in the results:

find /project/directory -iname '*.php' -or -iname '*.phtml' | grep -iv '/some/directory' | xargs xgettext

Whether or not there is an argument for find that will work 100%, I cannot say for certain. Using grep was a quick and easy solution after some headache.

Lemmings19
  • 1,002
  • 2
  • 17
  • 32
3

For those of you on older versions of UNIX who cannot use -path or -not

Tested on SunOS 5.10 bash 3.2 and SunOS 5.11 bash 4.4

find . -type f -name "*" -o -type d -name "*excluded_directory*" -prune -type f
JaredTS486
  • 426
  • 5
  • 15
3

The following commands works:

find . -path ./.git -prune -o -print

If You have a problem with find, use the -D tree option to view the expression analysis information.

find -D tree . -path ./.git -prune -o -print

Or the -D all, to see all the execution information.

find -D all . -path ./.git -prune -o -print
EIIPII
  • 1,631
  • 1
  • 16
  • 10
2

how-to-use-prune-option-of-find-in-sh is an excellent answer by Laurence Gonsalves on how -prune works.

And here is the generic solution:

find /path/to/search                    \
  -type d                               \
    \( -path /path/to/search/exclude_me \
       -o                               \
       -name exclude_me_too_anywhere    \
     \)                                 \
    -prune                              \
  -o                                    \
  -type f -name '*\.js' -print

To avoid typing /path/to/seach/ multiple times, wrap the find in a pushd .. popd pair.

pushd /path/to/search;                  \
find .                                  \
  -type d                               \
    \( -path ./exclude_me               \
       -o                               \
       -name exclude_me_too_anywhere    \
     \)                                 \
    -prune                              \
  -o                                    \
  -type f -name '*\.js' -print;         \
 popd
Community
  • 1
  • 1
go2null
  • 1,468
  • 1
  • 15
  • 17
  • 1
    From https://stackoverflow.com/questions/4210042/how-to-exclude-a-directory-in-find-command/16595367#16595367, I learned that the syntax used for the `-path` must match the name that find would print if it were to print the directory so, for example, `find . -path ./.git -prune -o -print`, or `find $HOME/foo -path $HOME/foo/.git -prune -o -print` Some of the answers just say `-path somedir` which unfortunately is not exact enough to be useful. – PatS Aug 05 '19 at 18:03
2

I tried command above, but none of those using "-prune" works for me. Eventually I tried this out with command below:

find . \( -name "*" \) -prune -a ! -name "directory"
ImportanceOfBeingErnest
  • 251,038
  • 37
  • 461
  • 518
Jolly Liu
  • 21
  • 1
2

For what I needed it worked like this, finding landscape.jpg in all server starting from root and excluding the search in /var directory:

find / -maxdepth 1 -type d | grep -v /var | xargs -I '{}' find '{}' -name landscape.jpg

find / -maxdepth 1 -type d lists all directories in /

grep -v /var excludes `/var' from the list

xargs -I '{}' find '{}' -name landscape.jpg execute any command, like find with each directory/result from list

adrianTNT
  • 3,046
  • 4
  • 24
  • 34
2

Another example when using multiple patterns -o -name

To search in the root directory / for all *.tpl, *.tf files, excluding files which reside in /src/.terraform/ and /code/.

$ find / -type f \( -name '*.tf' -o -name '*.tpl' \) \
  -and \( -not -path '/src/.terraform/*' -and -not -path '/code/*' \)


/src/debug.tf
/src/nodegroup-infra.tpl
/src/variables.tf.tpl

I tested the above command with hyperfine; The test was conducted on a system with 3k directories and 12k files. I think it's fair to say that it's fast enough ~70ms

Benchmark #1: ./entrypoint.sh
  Time (mean ± σ):      69.2 ms ±   1.4 ms    [User: 22.6 ms, System: 43.6 ms]
  Range (min … max):    66.4 ms …  72.2 ms    42 runs

Sample Directory Structure

/code/ directory tree

bash-5.0# tree /code
/code
├── debug.tf
├── entrypoint.sh
├── nodegroup-infra.tpl
├── tftemplate.sh
└── variables.tf.tpl

0 directories, 5 files

/src/ directory tree

bash-5.0# tree /src
/src
├── Dockerfile
├── debug.tf
├── entrypoint.sh
├── nodegroup-infra.tpl
├── terraform.tfstate
├── terraform.tfstate.backup
└── variables.tf.tpl

0 directories, 7 files

/ root directory tree summary

$ tree /
...
3382 directories, 12164 files
Meir Gabay
  • 1,356
  • 13
  • 20
2

If anyone's researching on how to ignore multiple paths at once. You can use bash arrays (works perfectly on GNU bash, version 4.4.20(1)-release)

#!/usr/bin/env bash

# This script helps ignore unnecessary dir paths while using the find command

EXCLUDE_DIRS=(
    "! -path /*.git/*"
    "! -path /*go/*"
    "! -path /*.bundle/*"
    "! -path /*.cache/*"
    "! -path /*.local/*"
    "! -path /*.themes/*"
    "! -path /*.config/*"
    "! -path /*.codeintel/*"
    "! -path /*python2.7/*"
    "! -path /*python3.6/*"
    "! -path /*__pycache__/*"
)
find $HOME -type f ${EXCLUDE_DIRS[@]}

# if you like fzf

find $HOME -type f ${EXCLUDE_DIRS[@]} | fzf --height 40% --reverse

Also for some reason, you won't be able to ignore /bin/ directory paths.

Bhupesh Varshney
  • 596
  • 8
  • 13
1

I found the functions name in C sources files exclude *.o and exclude *.swp and exclude (not regular file) and exclude dir output with this command:

find .  \( ! -path "./output/*" \) -a \( -type f \) -a \( ! -name '*.o' \) -a \( ! -name '*.swp' \) | xargs grep -n soc_attach
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Ivan Ivanovich
  • 736
  • 5
  • 11
1

Better use the exec action than the for loop:

find . -path "./dirtoexclude" -prune \
    -o -exec java -jar config/yuicompressor-2.4.2.jar --type js '{}' -o '{}' \;

The exec ... '{}' ... '{}' \; will be executed once for every matching file, replacing the braces '{}' with the current file name.

Notice that the braces are enclosed in single quote marks to protect them from interpretation as shell script punctuation*.


Notes

* From the EXAMPLES section of the find (GNU findutils) 4.4.2 man page

Alberto
  • 4,651
  • 3
  • 38
  • 64
  • 1
    Very old question, but still with room for improvements. I found it by chance trying to solve a similar problem, and none of the answers were satisfactory. – Alberto Aug 28 '15 at 08:27
  • I use the `exec` action often and find it very useful. I typically add quotes between the `{}` in case there are spaces in the file paths which gives `"{}"`. – Ludovic Kuty Dec 31 '15 at 08:06
  • @lkuty I was about to edit my post to reflect your comment, but after a quick test (without quoting, `{}` does work for files with whitespaces in their names) and a look into the man pages, it seems that quoting is only necessary to avoid them to be misinterpreted as shell script punctuation. In this case, you would use single quoting: `'{}'` – Alberto Jan 15 '16 at 13:52
  • I think that I had to use it to make `cp` or `mv` or `rm`. I will check it out – Ludovic Kuty Jan 15 '16 at 17:22
1

I consider myself a bash junkie, BUT ... for the last 2 years have not find a single bash user friendly solution for this one. By "user-friendly" I mean just a single call away, which does not require me to remember complicated syntax + I can use the same find syntax as before , so the following solution works best for those ^^^

Copy paste this one in your shell and source the ~/.bash_aliases :

cat << "EOF" >> ~/.bash_aliases
# usage: source ~/.bash_aliases , instead of find type findd + rest of syntax
findd(){
   dir=$1; shift ;
   find  $dir -not -path "*/node_modules/*" -not -path "*/build/*" \
      -not -path "*/.cache/*" -not -path "*/.git/*" -not -path "*/venv/*" $@
}
EOF

Of course in order to add or remove dirs to exclude you would have to edit this alias func with your dirs of choice ...

Yordan Georgiev
  • 4,006
  • 1
  • 43
  • 47
0

This works because find TESTS the files for the pattern "*foo*":

find ! -path "dir1" ! -path "dir2" -name "*foo*"

but it does NOT work if you don't use a pattern (find does not TEST the file). So find makes no use of its former evaluated "true" & "false" bools. Example for not working use case with above notation:

find ! -path "dir1" ! -path "dir2" -type f

There is no find TESTING! So if you need to find files without any pattern matching use the -prune. Also, by the use of prune find is always faster while it really skips that directories instead of matching it or better not matching it. So in that case use something like:

find dir -not \( -path "dir1" -prune \) -not \( -path "dir2" -prune \) -type f

or:

find dir -not \( -path "dir1" -o -path "dir2" -prune \) -type f

Regards

d0n
  • 221
  • 2
  • 4
0

For FreeBSD users:

 find . -name '*.js' -not -path '*exclude/this/dir*'
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
riba
  • 167
  • 2
  • 6
0

If search directories has pattern (in my case most of the times); you can simply do it like below:

find ./n* -name "*.tcl" 

In above example; it searches in all the sub-directories starting with "n".

Prince Bhanwra
  • 130
  • 1
  • 4
0

I have found the suggestions on this page and a lot of other pages just do not work on my Mac OS X system. However, I have found a variation which does work for me.

The big idea is to search the Macintosh HD but avoid traversing all the external volumes, which are mostly Time Machine backups, image backups, mounted shares, and archives, but without having to unmount them all, which is often impractical.

Here is my working script, which I have named "findit".

#!/usr/bin/env bash
# inspired by http://stackoverflow.com/questions/4210042/exclude-directory-from-find-command Danile C. Sobral
# using special syntax to avoid traversing. 
# However, logic is refactored because the Sobral version still traverses 
# everything on my system

echo ============================
echo find - from cwd, omitting external volumes
date
echo Enter sudo password if requested
sudo find . -not \( \
-path ./Volumes/Archive -prune -o \
-path ./Volumes/Boot\ OS\ X -prune -o \
-path ./Volumes/C \
-path ./Volumes/Data -prune -o \
-path ./Volumes/jas -prune -o \
-path ./Volumes/Recovery\ HD -prune -o \
-path ./Volumes/Time\ Machine\ Backups -prune -o \
-path ./Volumes/SuperDuper\ Image -prune -o \
-path ./Volumes/userland -prune \
\) -name "$1" -print
date
echo ============================
iMac2:~ jas$

The various paths have to do with external archive volumes, Time Machine, Virtual Machines, other mounted servers, and so on. Some of the volume names have spaces in them.

A good test run is "findit index.php", because that file occurs in many places on my system. With this script, it takes about 10 minutes to search the main hard drive. Without those exclusions, it takes many hours.

Jeffrey Simon
  • 702
  • 2
  • 9
  • 19
0

Not sure if this would cover all edge cases, but following would be pretty straight forward and simple to try:

ls -1|grep -v -e ddl -e docs| xargs rm -rf

This should remove all files/directories from the current directory excpet 'ddls' and 'docs'.

Arnab
  • 959
  • 1
  • 9
  • 16
  • https://unix.stackexchange.com/questions/128985/why-not-parse-ls-and-what-to-do-instead It is not recommended to pipe the output of "ls" – Ferdi Aug 05 '20 at 15:26
-1

i wanted to know the number of directories, files an MB of just the current directory - and that code does exactly what i want :-)

the source

- ...    2791037 Jun  2  2011 foo.jpg
- ... 1284734651 Mär 10 16:16 foo.tar.gz
- ...          0 Mär 10 15:28 foo.txt
d ...       4096 Mär  3 17:12 HE
d ...       4096 Mär  3 17:21 KU
d ...       4096 Mär  3 17:17 LE
d ...          0 Mär  3 17:14 NO
d ...          0 Mär  3 17:15 SE
d ...          0 Mär  3 17:13 SP
d ...          0 Mär  3 17:14 TE
d ...          0 Mär  3 19:20 UN

the code

format="%s%'12d\n"

find . -type d -not -path "./*/*" | wc -l | awk -v fmt=$format '{printf fmt, " Anzahl Ordner  = ", $1-1}'
find . -type f -not -path "./*/*" | wc -l | awk -v fmt=$format '{printf fmt, " Anzahl Dateien = ", $1}'
  du . -hmS --max-depth=0 | awk -v fmt=$format '{printf fmt, " Groesse (MB)   = ", $1}'

note: the extra format="%s%'12d\n" is necessary for awk to format the numbers.

the result

Anzahl Ordner  =            8
Anzahl Dateien =            3
Groesse (MB)   =        1.228
-1

Instead of:

for file in $(find . -name '*.js')
do 
  java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file
done

...and since you don't define which subdirectory you want to exclude, you could use:

for file in $(find *.js -maxdepth 0 -name '*.js')
do 
  java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file
done

This syntax will exclude all subdirectories.

Take a look at the example below: under my tmp directory I have an huge "archive" subdirectory which contains 17000-4640=12360 files. And this directory is located on a slow NFS. While the 1st syntax scans the "archive" subdirectory and performs poorly, the 2nd syntax only scans the "*pdf" files contained in my current dir and performs... not that bad.

[tmp]$ time (find . -name "*pdf" | wc -l)
17000

real    0m40.479s
user    0m0.423s
sys     0m5.606s

[tmp]$ time (find *pdf -maxdepth 0 -name "*pdf" | wc -l)
4640

real    0m7.778s
user    0m0.113s
sys     0m1.136s

That 2nd syntax is quite interesting: in the following example I want to check if file or60runm50958.pdf exists and is more than 20 minutes old. See for yourself how the 2nd syntax is more efficient. This is because it avoids scanning the archive subdirectory.

[tmp]$ time find . -name or60runm50958.pdf -mmin +20
./or60runm50958.pdf

real    0m51.145s
user    0m0.529s
sys     0m6.243s

[tmp]$ time find or60runm50958.pdf -maxdepth 0 -name or60runm50958.pdf -mmin +20
or60runm50958.pdf

real    0m0.004s
user    0m0.000s
sys     0m0.002s
FCA69
  • 85
  • 3
-2
#find command in linux
def : find command used to locate /search files in unix /linux system ,
      find  search for files in a directory hierarchy
1)exec   Show diagnostic information relating to -exec, -execdir, -ok and -okdir
2)-options
  -H =do not follow symoblic links while except while procesing .
  -L = follow symbolic links
  -P =never follow symbolic links

  -type c
             File is of type c:

             b      block (buffered) special

             c      character (unbuffered) special

             d      directory

             p      named pipe (FIFO)

             f      regular file

             l      symbolic  link;  this  is  never true if the -L option or the -follow option is in effect, unless the
                    symbolic link is broken.  If you want to search for symbolic links when -L is in effect, use -xtype.

             s      socket

             D      door (Solaris)

    -Delete
    Delete files; true if removal succeeded.  If the removal failed, an error message  is  issued.
    If  -delete
    #fails, find's exit status will be nonzero (when it eventually exits).


find /home/mohan/a -mindepth 3 -maxdepth 3 -type f -name "*.txt" |xargs rm -rf
find -type d -name
find -type f -Name
find /path/ -type f -iname (i is case insenstive)

#find directores a/b/c and only delete c directory inside have "*.txt "
find /home/mohan/a -mindepth 3 -maxdepth 3 -type f -name "*.txt" |xargs rm -rf
find /home/mohan/a -mindepth 3 -maxdepath 3 -type f -name "*.txt" -delete


#delete particular directory have empty file and only  we can delete empty files
find /home/mohan -type f -name "*.txt" -empty -DELETE


#find multiple files and also find empty files
find /home/mohan -type f \( -name "*.sh" -o  -name "*.txt" \) -empty

#delete empty files two or more Files
find /home/mohan -type f \( -nmae "*.sh" -o -name "*.txt" \) -empty -delete


#How to append contents of multiple files into one file
find . -type f -name '*.txt' -exec cat {} + >> output.file

#last modified files finding using less than 1 min (-n)
ls -lrth|find . -type f -mmin -1

#last modified files more than 1 min (+n)
ls -lrth|find . -type f -mmin +1


#last modified files exactly one mins
find . -type f -mmin 1

last modifiedfiles exactly in one day by using command (-mtime)
find . -type f -mtime 10

#last modified more than 10 days
find . -type  f -mtime +10

#last modified less than 10 days
find . -type f -mtime -10

#How to Find Modified Files and Folders Starting from a Given Date to the Latest Date
find . -type f  -newermt "17-11-2020"

#How to Find a List of “sh” Extension Files Accessed in the Last 30 Days--- -matdimtype
ls -lrt|find . -type f -iname ".sh" -atime -30

#How to Find a List of Files Created Today, -1 means less than min,
ls -lrt | find . -type f -ctime -1 -ls