Pruning all sub directories in the current directory - bash

tried to print all the files in the current directory using
find . -newer myfile -mtime +3 ! -name . -prune
but it is also printing the files in the sub directories
tried to read related post here :
How to use '-prune' option of 'find' in sh?
but did not understand but tried
find . -newer myfile -mtime +3 ! -name . -prune -o -print
this also did not bring what I wanted
also tried
find . -type f -newer myfile -mtime +3 ! -name . -prune
but this is bringing all .snapshots sub directories in the output recursively.
Please tell me how can I avoid all sub directories in the out put using prune.
OUTPUT
find . -newer myfile -mtime +3 ! -name . -prune
./.snapshot/hourly.7/file_status_out.txt
./.snapshot/hourly.1/file_status_out.txt
./.snapshot/hourly.6/file_status_out.txt
./.snapshot/hourly.5/file_status_out.txt
./.snapshot/nightly.0/file_status_out.txt
./.snapshot/hourly.0/file_status_out.txt
./.snapshot/hourly.4/file_status_out.txt
./.snapshot/hourly.2/file_status_out.txt
./.snapshot/hourly.3/file_status_out.txt
./.snapshot/nightly.2/file_status_out.txt
./.snapshot/nightly.1/file_status_out.txt
./.snapshot/veritas.nfs01p_vol1/file_status_out.txt
./.snapshot/weekly.0/file_status_out.txt
./.snapshot/lonnf30060(1874649454)_nfs01p_vol1.58917/file_status_out.txt
./.snapshot/lonnf30060(1874649454)_nfs01p_vol1.58916/file_status_out.txt
./.snapshot/dfpm_base(dataset-id-225039)conn1.0/file_status_out.txt
./file_status_out.txt

It depends on the last modification time of "myfile", implicitly find does a -and or -a with the expressions, so the paths to prune are (directory files) newer than myfile -newer myfile and -mtime +3 with last modification time greater than 3 days, this may be not possible if myfile is more recent than 3 days.
Another solution to prune directories if -maxdepth is not supported
find . ! -name . -type d -prune -o -print
specific condition can be added after -o
find . ! -name . -type d -prune -o -newer myfile -print
update following comments, it seems conditions are not added at the right place:
find . ! -name . -type d -prune -o -newer myfile -mtime +1 -print
conditions before -prune are to filter subdirectories (type d except . otherwise would return nothing), conditions after -o are to filter files to -print or to -ls depending the last argument

Related

Need to find files with multiples arguments in bash

I've done this atm, I need to find in the main directory and in the sub-directory everything starting with the letter 'a', every files ending with 'z' and every files starting with 'z' and ending with 'a!'.
find . -name "a*" | find . "*z" -type f | find . "z*a!" -type f
I tried to be as clear as possible, sorry if it wasn't clear enough.
find . -type f \( -name 'a*' -or -name '*z' -or -name 'z*a!' \)
Use -o instead of -or for POSIX compliance.
If you really want to also find links, directories, pipes etc. starting with a but only files matching the remaining conditions, you can do
find . -name 'a*' -or -type f \(-name '*z' -or -name 'z*a!' \)
TL;DR
find . -name 'a*' -o -type f \( -name '*z' -o -name 'z*a!' \)
Explanations:
The find logical operators are -a (AND) and -o (OR). You use them to combine elementary tests. Note that because of operator's precedence you sometimes need parentheses and that they must be escaped (with \) to prevent their interpretation by the shell. Your test is:
everything starting with the letter 'a': -name 'a*'.
every files ending with 'z': -type f -a -name '*z'.
every files starting with 'z' and ending with 'a!': -type f -a -name 'z*a!'.
So the complete test could be:
-name 'a*' -o \( -type f -a -name '*z' \) -o \( -type f -a -name 'z*a!' \)
As -a is the default we can omit it, and as -type f (file) is common to the two last terms of the disjunction we can factor it:
-name 'a*' -o -type f \( -name '*z' -o -name 'z*a!' \)

find and delete folder and/or zip file in a directory [duplicate]

I was trying to get a list of all python and html files in a directory with the command find Documents -name "*.{py,html}".
Then along came the man page:
Braces within the pattern (‘{}’) are not considered to be special (that is, find . -name 'foo{1,2}' matches a file named foo{1,2}, not the files foo1 and foo2.
As this is part of a pipe-chain, I'd like to be able to specify which extensions it matches at runtime (no hardcoding). If find just can't do it, a perl one-liner (or similar) would be fine.
Edit: The answer I eventually came up with include all sorts of crap, and is a bit long as well, so I posted it as an answer to the original itch I was trying to scratch. Feel free to hack that up if you have better solutions.
Use -o, which means "or":
find Documents \( -name "*.py" -o -name "*.html" \)
You'd need to build that command line programmatically, which isn't that easy.
Are you using bash (or Cygwin on Windows)? If you are, you should be able to do this:
ls **/*.py **/*.html
which might be easier to build programmatically.
Some editions of find, mostly on linux systems, possibly on others aswell support -regex and -regextype options, which finds files with names matching the regex.
for example
find . -regextype posix-egrep -regex ".*\.(py|html)$"
should do the trick in the above example.
However this is not a standard POSIX find function and is implementation dependent.
You could programmatically add more -name clauses, separated by -or:
find Documents \( -name "*.py" -or -name "*.html" \)
Or, go for a simple loop instead:
for F in Documents/*.{py,html}; do ...something with each '$F'... ; done
This will find all .c or .cpp files on linux
$ find . -name "*.c" -o -name "*.cpp"
You don't need the escaped parenthesis unless you are doing some additional mods. Here from the man page they are saying if the pattern matches, print it. Perhaps they are trying to control printing. In this case the -print acts as a conditional and becomes an "AND'd" conditional. It will prevent any .c files from being printed.
$ find . -name "*.c" -o -name "*.cpp" -print
But if you do like the original answer you can control the printing. This will find all .c files as well.
$ find . \( -name "*.c" -o -name "*.cpp" \) -print
One last example for all c/c++ source files
$ find . \( -name "*.c" -o -name "*.cpp" -o -name "*.h" -o -name "*.hpp" \) -print
I had a similar need. This worked for me:
find ../../ \( -iname 'tmp' -o -iname 'vendor' \) -prune -o \( -iname '*.*rb' -o -iname '*.rjs' \) -print
My default has been:
find -type f | egrep -i "*.java|*.css|*.cs|*.sql"
Like the less process intencive find execution by Brendan Long and Stephan202 et al.:
find Documents \( -name "*.py" -or -name "*.html" \)
Braces within the pattern \(\) is required for name pattern with or
find Documents -type f \( -name "*.py" -or -name "*.html" \)
While for the name pattern with and operator it is not required
find Documents -type f ! -name "*.py" -and ! -name "*.html"
#! /bin/bash
filetypes="*.py *.xml"
for type in $filetypes
do
find Documents -name "$type"
done
simple but works :)
I needed to remove all files in child dirs except for some files. The following worked for me (three patterns specified):
find . -depth -type f -not -name *.itp -and -not -name *ane.gro -and -not -name *.top -exec rm '{}' +
This works on AIX korn shell.
find *.cbl *.dms -prune -type f -mtime -1
This is looking for *.cbl or *.dms which are 1 day old, in current directory only, skipping the sub-directories.
find MyDir -iname "*.[j][p][g]"
+
find MyDir -iname "*.[b][m][p]"
=
find MyDir -iname "*.[jb][pm][gp]"
What about
ls {*.py,*.html}
It lists out all the files ending with .py or .html in their filenames

In BASH, find folders that match different names

I would like to find all my sub-folders that match with different names and that are older than X days
I tried with just one name:
find my_folder -maxdepth 3 -type d -name "*mine*" -mtime +30
This works ok. I don't know how to extend this in order to match also folders with "test" and "older" names
You can use -o to OR the conditions and make sure to use parentheses around ORed directives:
find my_folder -maxdepth 3 -type d \( -name "*mine*" -o -name "*test*" -o -name "*older*" \) -mtime +30
Another alternative is using -regex option:
find my_folder -regextype posix-extended -maxdepth 3 -type d -regex '.*(minetest|older).*" -mtime +30

Bash/Shell Combine options using find

Using the find command is there a way to combine options:
i.e.
find . -type fd -name "somefile"
Although -type ignores the second option; I'm looking to find only files or directories.
You can use -o for OR condition in find:
find . \( -type d -o -type f \) -name "somefile"

Listing files with size greater than N

I need to list all files with size > 0 under a directory (where it's actually expected that the file size is 0). How can I do it with grep and/or awk? I was thinking of something like
$ ls -alR | grep ... | awk ...
Yet another find option:
find . ! -empty
update: (thanks to #steve comment)
If you need to list only files in only current directory:
find . -maxdepth 1 -type f ! -empty
Note that -maxdepth is GNU feature. In POSIX environment there is another way:
find -type f -o \( ! -name . -type d -prune -false \) ! -empty

Resources