Exclude a subpath in find command [duplicate] - linux

This question already has answers here:
How do I exclude a directory when using `find`?
(46 answers)
Closed 7 years ago.
I have the following find command:
find /mnt/F_11 -type f \( -iname '*.xls' -o -iname '*.xlsx' /)
How would I find all items in /mnt/F_11 but not in /mnt/f_11/DONOTENTER/?
In other words, I would want it to search:
YES /mnt/F_11
YES /mnt/F_11/somepath/
YES /mnt/F_11/somepath/other/
NO /mtn/F_11/DONOTENTER/

Use -prune to avoid recursing down branches you don't want to follow.
find /mnt/F_11 -name DONOTENTER -prune -o \
-type f \( -iname '*.xls' -o -iname '*.xlsx' \) -print
Note the explicit -print at the end -- this is important, as otherwise the implicit print action covers both branches.

Related

How to write a bash script to find files with complex conditions [duplicate]

This question already has answers here:
Expanding a bash array only gives the first element
(1 answer)
Why does shell ignore quoting characters in arguments passed to it through variables? [duplicate]
(3 answers)
Closed 11 months ago.
Expected Function: write a bash script showing all the regular files
with filename ended with ".xml" or ".yml" and with path not begined
with "./target/", i.e., exclude the "target" subdirectory.
Example File List: ./a/a1.xml; ./a/a2.txt; ./b/b1.yml; ./target/t.xml;
Example Outout: ./a/a1.xml; ./b/b1.yml
I construct find options in a bash shell script like
#!/bin/bash
find_opts=( -type f -a ( -not -path "./target/*" ) -a ( -false -o -name "*.xml" -o -name "*.yml" ) )
find . $find_opts
But it does not output the expected result. Howver, when I tpye the full command string in bash terminal as follows:
[root#localhost]#find . \( -type f -a \( -not -path "./target/*" \) -a \( -false -o -name "*.xml" -o -name "*.yml" \) \)
it works. What is the problem about the above bash script ?
==============================================================
Someone gives this reference link : Expanding a bash array only gives the first element
It is about "bash array". But it seems that my problem is not about "bash array". Would anyone give any reasons?
Please see How to exclude a directory in find . command to known why I use parentheses whiches look like an array. Anyway, I try two others attempts:
#the first one
find_opts=( -type f -a ( -not -path "./target/*" ) -a ( -false -o -name "*.xml" -o -name "*.yml" ) )
#the second one
find_opts=\\( -type f -a \\( -not -path "./target/*" \\) -a \\( -false -o -name "*.xml" -o -name "*.yml" \\) \\)
#the third one
find_opts=\( -type f -a \( -not -path "./target/*" \) -a \( -false -o -name "*.xml" -o -name "*.yml" \) \)
The first one and the third one give the same output which is unexpeced result. The second one occures an error.
syntax error near unexpected token `('
The problem is still here.
==============================================================
Someone give one more reference:Why does shell ignore quoting characters in arguments passed to it through variables?
It is about how to use bash array to pass arguments and the problem is solved by the following code:
#!/bin/bash
find_opts=(\( -type f -a \( -not -path './target/*' \) -a \( -false -o -name '*.xml' -o -name '*.yml' \) \))
find . "${find_opts[#]}"

Combine two find commands in one

I currently have the following line:
find . -type f ! -name "*.xml" -delete && find . -type d -empty -delete
But as they are 2 find commands, I suppose I can merge them into one. But I don't want to use -exec.
I wan't to use something native in bash, that comes preinstalled with any linux distro.
You can group primaries with the -o ("or", as opposed to the implict "and" that find applies to its primaries) primary. The parentheses are escaped to avoid shell syntax errors and ensure they are passed as arguments to find.
find . \( \( -type f ! -name "*.xml" \) -o \( -type d -empty \) \) -delete

FInd patternf for multiple pattern of files

I need to search for multiple pattern of files and check their mtime and if it morethan 30 days then delete all the files. I am using the below command but it's deleting only one pattern of file and not all. Kindly let me know where is the mistake in my command.
find /root -type f \( -name "*.tgz" -o -name "*.bz2" \) -mtime +30 -print -exec rm '{}' +
Try escaping parentheses in the command and adding a wildcard character:
find /root -type f \( -name "*.tgz" -o -name "*.bz2" \) -mtime +30 -exec rm {} \+

Using "find … -delete" to remove image files only from special subdirectories

I need to clean up some subdirectories inside my music collection from unwanted images. I’m using Ubuntu 14.04 and/or Linux Mint 17.2 and a bash shell script using the find command.
The directory structure (minimal example) is as follows:
Tagged
Artist #1
Artist #1 - An Album
Artist #1 - A Track.flac
cover.jpg
something.png
Artist #1 - [compilations]
Artist #1 - A Track.flac
cover.jpg
something.png
Artist #2
Artist #2 - Another Album
Artist #2 - A Track.mp3
cover.jpg
Only in the subfolders ending with "[compilations]", I want to delete all kind of jpeg and/or png images (because the tagging software erroneously puts them there). Any images that happen to be in normal "album" folders I wish too keep.
With my directory structure, folders with "[compilations]" in the name can only happen just below the "Artist" folders, repectively; so a maximum of two levels deep.
I came up with the following find command:
$ cd Tagged
$ find . -maxdepth 2 -type d -name '*\[compilations\]' -exec find {} -type f -iname '*.jp*g' -or -iname '*.png' -delete \;
This seems to do something and takes a while, but the files "./Artist #1/Artist #1 - [compilations]/cover.jpg" and "./Artist #1/Artist #1 - [compilations]/something.png" are still there (and all other image files).
Being quite new to Linux, I assume I make a dumb mistake using find's -delete option, because the following command (without -delete) shows the files correctly:
$ find . -maxdepth 2 -type d -name '*\[compilations\]' -exec find {} -type f -iname '*.jp*g' -or -iname '*.png' \;
./Artist #1/Artist #1 - [compilations]/cover.jpg
./Artist #1/Artist #1 - [compilations]/something.png
So here are my questions:
Why does the -delete not work?
Is this command really safe regarding "extravaganza" like whitespace, glob characters and foreign characters in the paths and filenames?
How would I have to rewrite the above command, still using bash and find?
Could the command be optimized (re speed, safety, nested finds)?
In the actual collection, the command must traverse 16899 folders, almost all of them contain whitespace and foreign characters (like Czech, Russian, Japanese, Greek, German …), so it must be robust.
Thanks in advance for any insights and some enlightenment!
Your -delete predicate only applies to the
-iname '*.png'
predicate, because you missed groupings: when you give find the following:
-type f -iname '*.jp*g' -or -iname '*.png' -delete
because of the precedence of the boolean operators, find understands:
\( -type f -iname '*.jp*g' \) -or \( -iname '*.png' -delete \)
To fix this, use:
-type f \( -iname '*.jp*g' -or -iname '*.png' \) -delete
I'd suggest that to experiment you replace -delete with -print: you'll see what the -delete applies to!
Now, regarding your nested find: because of the structure of your directory tree (your files are only in depth 3), you should be able to do with only one instance of find:
find -maxdepth 3 -path '*/*\[compilations\]/*' \( -iname '*.jp*g' -o -iname '*.png' \) -type f -print
(I put -print instead of -delete so that you can check the command before executing it with -delete).
After some experimentation, I think my error was in not putting the OR'ed part in parentheses—it seems find used the -delete only on the right part of the last OR, i.e., tried to delete '*.png'. Alas, almost all of my cover images were '*.jpg' so I thought it wouldn't work at all!
So I think the corrected command should be:
$ find . -depth -maxdepth 2 -type d -name '*\[compilations\]' -exec find {} -type f \( -iname '*.jp*g' -or -iname '*.png' \) -delete \;
It seems to work correctly on my test case above.
Nevertheless, some confirmation would be nice. An maybe some answers to my other questions, just for information and learning. Thank you!

Want to find any reference in any file to a certain string in linux [duplicate]

This question already has answers here:
how to find files containing a string using egrep
(7 answers)
Closed 8 years ago.
I am trying to search All .PHP files or ALL .SH files for any reference that contains:
'into tbl_free_minutes_mar'
I have command line access to the server but the files may be scattered in different directories.
For all directories everywhere,
find / -type f \( -name '*.php' -o -name '*.sh' \) \
-exec fgrep 'into tbl_free_minutes_mar' {} \+
For fewer directories elsewhere, just give a list of paths instead of /. To just list the matching files, try fgrep -l. If your file names might not always match the wildcards in the -name conditions, maybe scan all files.
find / -type f \( -name \*.php -o -name \*.sh \) -exec grep 'into tbl_free_minutes_mar' {} /dev/null \;
Change find / ... to to something less all-encompassing if you know the general area that you want to look in, e.g. find /home ...
Provided /base/path is the path where you want to start looking this will get you a list of files:
find /base/path -type f -iregex '.*\.\(php\|sh\)$' -exec grep -l 'into tbl_free_minutes_mar' '{}' \;

Resources