find h files using iregex Bash - bash

I'm using this line to find h files using bash but when it does it also finds bash files because of the .sh ending and I'm not sure how i can limit the find to only find files with a .h not a . and some h as last character.
find . -iregex '.*\(h\)'

What about the much simpler
find -iname '*.h'
This is better because it does only find files that end in .h and is maybe faster then using a full regex.
For regex the right approach is
find -iregex '\.h$'
the \. escapes the '.' so that it matches a '.'. And the $ tells it it should be the last part in the match.
Added because of question in comment:
Normally
find \( -iname '*.h' -or -iname '*.c' \)
works fine for me. The \( \) is to escape the parenthesis from the shell.

You can use enhanced regex with anchor $ to only match .h:
find . -iregex '.*\.h$'

Related

find files and exclude several file endings from the result for a posix shell

I want to have a single line command to find files recursive and be able to exclude several file types by there file ending.
This is what I came up with and it works.
find "$path" -type f \( ! -iname "*.txt" ! -iname ".*" ! -iname "*.swf" \)
but my problem is:
If I want to exclude more files the command gets really long.
I would prefer to have the option to put all excluded file endings in one variable to have something similar like this exclude="(*.txt|*.swf|.*)"; find "$path" -type f \( ! -iname "$exclude" \) (I know that this code doesn't work but as an explanation what I try to get.)
Like said above, it drives me crazy that I'm not able to find a short single line command which is posix compliant and is able to find files recursive and is able to exclude file by there file ending.
The nearest solution I found is https://stackoverflow.com/a/22558474 but in this solution a file is used to store the to be excluded files. So it's not a single line command.
Thanks in advance!
Assuming you don't have any newlines in filenames, you can pipe the output of find through grep to filter out unwanted ones using a regular expression:
find "$path" -type f | grep -Ev '(^\.)|(\.(txt|swf)$)'

Bash Find with ignore

I need to find files and ignore files like "^02" (it is regex). If "^02" is directory, then I need to ignore every files, which are inside directory. I don't know how to do it. I tried to use something like.
find . -type f -not -regex "^9" -o -prune
But it doesn't works.
Note that the regex doesn't use ^ and $ as it always has to match the whole string. Moreover, the path starts with ./ if the first argument to find is ., so you need to include it, too.
find -type f -not -regex '\./02.*'
If you want to exclude even subdirectories, use .*/02.* for the regex.
If you want to only exclude the directories matching the pattern, but you want to keep the files, you need to use prune only for directories matching the regex, and -false to remove the directories from the list:
find . -type d -regex '\./02.*' -prune -false -or -type f
Also, you can use patterns instead of regexes for simple cases. That way, you can use -name to include subdirectories:
find . -name '02*' -prune -false -or -type f

Match .h, .m, .mm files but NOT .html

I want to do some processing on just the source files of type .h, .m, .mm. I do NOT want to include the .html files.
The following misses the .mm files as I'm only matching .h or .m and not trying to catch longer extensions.
find ./ -type f -name "*.[hm]"
This only catches the .mm files, as the ? operator always matches a character. I'd like it to be an optional zero or one match like in regex.
find ./ -type f -name "*.[hm]?"
But if I use * instead, it matches 0 or multiple characters. This returns everything, but also has the .html files that I don't want.
find ./ -type f -name "*.[hm]*"
Any ideas on how to do this?
You can combine conditions:
find -type f -and \( -name '*.h' -or -name '*.m' -or -name '*.mm' \)
Or:
find ./ -type f -and -name '*.[hm]*' -and -not -name '*.html'
You were running OS X. There is -E switch that you can use to tell find that the regular expression is an extended expression.
Interpret regular expressions followed by -regex and -iregex primaries as extended (modern) regular expressions rather than basic regular expressions (BRE's). The re_format(7) manual page fully describes both formats.
Your command should now work:
find -E . -type f -regex ".*\.([hm]|mm)"

How to search filenames by regex with "find"

I was trying to find all files dated and all files 3 days or more ago.
find /home/test -name 'test.log.\d{4}-d{2}-d{2}.zip' -mtime 3
It is not listing anything. What is wrong with it?
find /home/test -regextype posix-extended -regex '^.*test\.log\.[0-9]{4}-[0-9]{2}-[0-9]{2}\.zip' -mtime +3
-name uses globular expressions,
aka wildcards. What you want is
-regex
To use intervals as you intend, you
need to tell find to use Extended
Regular Expressions via the
-regextype posix-extended flag
You need to escape out the periods
because in regex a period has the
special meaning of any single
character. What you want is a
literal period denoted by \.
To match only those files that are
greater than 3 days old, you need to prefix your number with a + as
in -mtime +3.
Proof of Concept
$ find . -regextype posix-extended -regex '^.*test\.log\.[0-9]{4}-[0-9]{2}-[0-9]{2}\.zip'
./test.log.1234-12-12.zip
Use -regex not -name, and be aware that the regex matches against what find would print, e.g. "/home/test/test.log" not "test.log"
Start with:
find . -name '*.log.*.zip' -a -mtime +1
You may not need a regex, try:
find . -name '*.log.*-*-*.zip' -a -mtime +1
You will want the +1 in order to match 1, 2, 3 ...
Use -regex:
From the man page:
-regex pattern
File name matches regular expression pattern. This is a match on the whole path, not a search. For example, to match a file named './fubar3', you can use the
regular expression '.*bar.' or '.*b.*3', but not 'b.*r3'.
Also, I don't believe find supports regex extensions such as \d. You need to use [0-9].
find . -regex '.*test\.log\.[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\.zip'
Just little elaboration of regex for search a directory and file
Find a directroy with name like book
find . -name "*book*" -type d
Find a file with name like book word
find . -name "*book*" -type f

Ignore/prune hidden directories with GNU find command

When using the find command, why is it that the following will successfully ignore hidden directories (those starting with a period) while matching everything else:
find . -not \( -type d -name ".?*" -prune \)
but this will not match anything at all:
find . -not \( -type d -name ".*" -prune \)
The only difference is the question mark. Shouldn't the latter command likewise detect and exclude directories beginning with a period?
The latter command prunes everything because it prunes . - try these to see the difference:
$ ls -lad .*
.
..
.dotdir
$ ls -lad .?*
..
.dotdir
You see that in the second one, . isn't included because it is only one character long. The glob ".?*" includes only filenames that are at least two characters long (dot, plus any single character, non-optionally, plus any sequence of zero or more characters).
By the way, find is not a Bash command.
The latter command prunes . itself -- the directory you're running find against -- which is why it generates no results.

Resources