Using find to delete all files (without sub dir) - bash

Here is the structure of my dir:
./archive
/sub1
- file1
- file2
/sub2
- file3
- file4
I try with this command to find all the files that older than 6 months to delete it:
find ./archive -mindepth 1 -mtime +180 -delete
All the files and sub directory is deleted, what I want just the file1, file2, file3, file4 that delete, not include the sub1 and sub2, please advise.

find supports the -type option. Use that to specify regular file with f as the argument.
find ./archive -mindepth 1 -mtime +180 -delete -type f

include a -type f flag that restricts the find to only files:
find ./archive -mindepth 1 -mtime +180 -delete -type f

Add -type f option to exclude directories:
find ./archive -mindepth 1 -mtime +180 -type f -delete

Related

How to exclude CWD in a `find` command [duplicate]

This question already has answers here:
How to exclude this / current / dot folder from find "type d"
(5 answers)
Closed 2 years ago.
How can I exclude the current working directory (CWD) with find?
Consider my current working directory to contain the following directories (ls .):
a b c d e f g
Find command: find . -maxDepth 1 -type d will return:
.
./a
./b
./c
./d
./e
./f
./g
I tried the answer from here (How to exclude a directory in find . command): find . -maxdepth 1 -type d -path . -prune -false
While I can use ls I'd be curious how I could achieve the same with find.
So the expected output from a find command should be similar to the ls . output:
./a
./b
./c
./d
./e
./f
./g
You can use -mindepth 1 option to avoid matching . (current) directory:
find . -mindepth 1 -maxdepth 1 -type d
To be able to match only single character directories:
find . -mindepth 1 -maxdepth 1 -type d -name '?'
Could you please try following, assuming you are setting maxdepth to 1 because you need to get only current directory's all directories.
find . -maxdepth 1 -type d \( ! -name '.' \) -print
I think also this should work: find . -maxdepth 1 -type d -\! -name "." -prune

List all unique directories that contain string1 that contain files that contain string2

Say I want to find all directories that contain a certain string (say a here) that also contain files that contain a certain other string (say that are .txt files). What are the different ways of doing this? One way is to do a command substitution, such as:
mkdir dira; mkdir dirb
touch dira/file1.txt; touch dira/file2.doc; touch dirb/file3.doc
find `find . -type d -iname '*a'` -type f -iname '*.doc'
However, this does not work if I am trying to find hidden directories that contain this file:
find `find . -type d -iname '.*'` -type f -iname '*.doc'
In this case, it just prints to stdout the inside find. How does one do this? The more ways to do this, the more instructive. A shell script would also be instructive.
This works for me:
#!/bin/bash
# Setup test directories
mkdir dira dirb .dirc .dird .hiddena
# Setup test files
touch dira/filea1.doc dira/filea2.doc dira/filea3.txt
touch dirb/fileb1.doc dirb/fileb2.doc dirb/fileb3.txt
touch .dirc/filec1.doc .dirc/filec2.doc .dirc/filec3.txt
touch .dird/filed1.doc .dird/filed2.doc .dird/filed3.txt
touch .hiddena/filehiddena1.doc .hiddena/filehiddena2.doc .hiddena/filehiddena3.txt
find . -type d -name "*a" -print | while read DIR
do
find $DIR -type f -name "*a*.doc" -print
done
Output:
$ ./t.bash
./dira/filea1.doc
./dira/filea2.doc
./.hiddena/filehiddena2.doc
./.hiddena/filehiddena1.doc
My first version used a for loop but that can cause issues if you have spaces in your directory names, thus the while read loop.
From your comment, I did this:
# Setup test directories
mkdir dira dirb .dirc .dird .hiddena
# Setup test files
touch dira/filea1.doc dira/filea2.doc dira/filea3.txt
touch dirb/fileb1.doc dirb/fileb2.doc dirb/fileb3.txt
touch .dirc/filec1.doc .dirc/filec2.doc .dirc/filec3.txt
touch .dird/filed1.doc .dird/filed2.doc .dird/filed3.txt
touch .hiddena/filehiddena1.doc .hiddena/filehiddena2.doc .hiddena/filehiddena3.txt
touch .hiddena/z
find . -type d -name "*a" -print | while read DIR
do
#find $DIR -type f -name "*a*.doc" -print
find $DIR -type f -name z -print
done
The output I get is:
$ ./t.bash
./.hiddena/z
So I do not understand why you get double z.
To prevent the actual directory being evaluated (as ./ or ../pwd/), just use:
find .* -mindepth 1 -maxdepth 1 -type f -iname '*.doc'
.dira/file11.doc
.dira/file10.doc
.dira/file9.doc
.dirb/file11.doc
.dirb/file10.doc
.dirb/file9.doc
After using
touch .dir{a..b}/file{9..11}.doc
with the longer pattern .dir* it is more easy:
find .dir* -type f -iname '*.doc'
.dira/file11.doc
.dira/file10.doc
.dira/file9.doc
.dirb/file11.doc
.dirb/file10.doc
.dirb/file9.doc
Command substitution works too (don't use the outdated backticks, please)
find $(find . -mindepth 1 -type d -iname ".*") -type f -iname '*.doc'
./.dirb/file11.doc
./.dirb/file10.doc
./.dirb/file9.doc
./.dira/file11.doc
./.dira/file10.doc
./.dira/file9.doc

Pruning all sub directories in the current directory

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

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

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