Using find with variable inside regex - linux

I am trying to use find in order to get a targeted file for my sh script
PREVIOUS_FILE="FX00.txt"
var=$(find /usr1/fida -regextype posix-extended -regex "$PREVIOUS_FILE\.(ok|false)")
When execution ends var is empty.
I want to find
FX00.txt.ok
If I execute it in normal shell it works.Any suggestions?
Best regards!

According to the find's manual:
-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 f.*r3.

Related

How to ignore a file using find command

I'm trying to find artifact using the command
name: Get path to Java artifact
run:echo JAVA_ARTIFACT=$(findbuild/libs/*.jar -type f) >>$GITHUB_ENV
The problem is I have 2 artifacts in that directory
build/libs/abc.jar
build/libs/abc-plain.jar
I want to pick only abc.jar file.
Can anyone suggest how can I achieve this ?
The find command can be used with regular expressions which makes it easy to get any kind of complex search results. How it works:
You have to use your find command with -regex instead of -name.
You have to generate a matching regular expression
How find passes the filename to the regular expression?
Assume we have the following directory structure:
/home/someone/build/libs/abc.jar
/home/someone/build/libs/abc-plain.jar
and we are sitting in someone
if we execute find . without any further arguments, we get:
./build/libs/abc.jar
./build/libs/abc-plain.jar
So we can for example search with regex for:
something starts with a single dot .
may have some additional path inside the file name
should NOT contain the - character in any number of character
ends with .jar
This results in:
'.'
'/*'
'[^-]+'
'.jar'
And all together:
find . -regex '.*/[^-]+.jar'
or if you ONLY want to search in build/libs/
find ./build/libs -regex '.*/[^-]+.jar'
You find a online regex tool there.
The find command support standard UNIX regex to match, include or exclude files. You can write complex queries easily with regex while finding the command recursively descends the directory tree for each /file/to/path listed, evaluating an expression.
Since you haven't clearly mentioned that you don't want the hyphen - in the filename, I'm assuming to find files without -.
I would try something like this. Matching lower-case, upper-case, numerical & .jar extension with regex.
find build/libs/ -regextype posix-egrep -regex '.*/[a-zA-Z0-9]+\.jar'
I got below output when tested locally.
touch abc.jar
touch abc-plain.jar
find . -regextype posix-egrep -regex '.*/[a-zA-Z0-9]+\.jar'
./abc.jar
You can try above commands here

Shell script find command for matching file names with one or the other word

I am looking for a command for bash shell script to find the list of files in a directory whose names start with either WordA or WordB and end with digits.
I have this command with WordA and duplicating the same code with WordB.
find /log/ -name 'WordA*[[:digit:]]'
I tried putting Or condition in various formats such as (WordA|WordB), [WordA|WordB], [(WordA)|(WordB)], [(WordA)||(WordB)] to match WordA or WordB followed by digits.
None of them worked.
You need to use the -regextype supported in find command, in the case used the posix-extended type and do
-regextype type
Changes the regular expression syntax understood by -regex and -iregex
tests which occur later on the command line. Currently-implemented
types are emacs (this is the default), posix-awk, posix-basic,
posix-egrep and posix-extended.
So your command should be
find /log/ -regextype posix-extended -regex './(WordA|WordB)([[:digit:]]+)$'
In the find man page, under header Expressions, you'll find (no pun intended) the following
Operators
Operators join together the other items within the expression.
They include for example -o (meaning logical OR) and -a (meaning
logical AND). Where an operator is missing, -a is assumed.
Thus the answer to your problem appears to be
find /log/ -name 'WordA*[[:digit:]]' -o 'WordB*[[:digit:]]'

Linux find command shell expansion

I have just a little question I don't understand with the find command.
I can do this :
[root#hostnaoem# ❯❯❯ls /proc/*/fd
But this give me an error :
[root#hostnaoem# ❯❯❯ find /proc/*/fd -ls
find: `/proc/*/fd': No such file or directory
even if I use "/proc//fd", /proc/""/fd or "/proc/*/fd"
I've searched wha find shell expansion says about that, but I found nothing. Can someone tell me why?
Thanks
If you just RTFM, you'll learn that the syntax for find is:
find [-H] [-L] [-P] [-D debugopts] [-Olevel] [path...] [expression]
The usually used subset of that is:
find whereToSearch (-howToSearch arg)*
To find all files|directories named fd in /proc:
find /proc -name fd
-name is the most common howToSearch expression:
-name pattern
Base of file name (the path with the leading directories
removed) matches shell pattern pattern. The metacharacters
(`*', `?', and `[]') match a `.' at the start of the base name
(this is a change in findutils-4.2.2; see section STANDARDS CON‐
FORMANCE below). To ignore a directory and the files under it,
use -prune; see an example in the description of -path. Braces
are not recognised as being special, despite the fact that some
shells including Bash imbue braces with a special meaning in
shell patterns. The filename matching is performed with the use
of the fnmatch(3) library function. Don't forget to enclose
the pattern in quotes in order to protect it from expansion by
the shell.
(Note the the last sentence)
If your pattern contains slashes, you need -path or -wholename (same thing):
find /proc/ -wholename '/proc/[0-9]*/fd' 2>/dev/null
Other expressions you might want to use are:
-type
-depth, -mindepth, -maxdepth
-user, -uid
See find(1) to learn more about each search expressions. If you want to search the in-terminal manual (man find or man 1 find), you can use the / character to enter search mode (like Ctrl+F in most GUI apps).
Usage of ls with globbing (*) is generally a code smell. Unless you use the -d flag, it'll list the contents of the directories that match the glob pattern in addition to the matches.
I find the echo globpattern form generally more convenient for viewing the results of a glob pattern match.
This work :
[root#hostname # ❯❯❯ find /proc/ -path /proc/*/fd -ls
Regards.

Problem using 'find' in BASH

I'm following this guide to get some basic skills in Linux.
At the exercises of chapter 3 section, there are two exercises:
*Change to your home directory. Create a new directory and copy all
the files of the /etc directory into it. Make sure that you also copy
the files and directories which are in the subdirectories of /etc!
(recursive copy)
*Change into the new directory and make a directory for files starting
with an upper case character and one for files starting with a lower
case character. Move all the files to the appropriate directories. Use
as few commands as possible.
The first part was simple but I have encountered problems in the second part (although I thought it should be simple as well).
I did the first part successfully - that is, I have a copy of the /etc folder in ~/newetc - with all the files copied recursively into subdirectories.
I've created ~/newetc/upper and ~/newetc/lower directories.
My intention was to do something like mv 'find ... ' ./upper for example.
But first I thought I should make sure that I can find all the files with Upper/Lower case seperately. At this I failed.
I thought that find ~/newetc [A-Z].* (also tried: find ~/newetc -name [A-Z].*) to find all the upper case files - but it simply returns no results.
What's even stranger: find ~/newetc -name [a-z].*) returns only two files, although of course there are a lot more then that...
any idea what am I doing wrong?
Thank you for your time!
Edit: (I have tried to read the Man for find command btw, but didn't come up with anything)
The -name argument does not take a full regular expression by default. So [A-Z].* will match only if the second character is a dot.
Use the expression [A-Z]*, or use -regex and -regextype to match using a real regex.
You need to use quotes
find ~/new_etc -name "[A-Z]*"
find ~/new_etc -name "[a-z]*"
If you want to use regexp, then you must use -regex (or -iregex).
For finding stuff, the other answers tell you how to do it.
For moving the results of find, use the -exec flag (while being in newetc):
find -name "[A-Z]*" -exec mv {} upper/{} \;
find -name "[a-z]*" -exec mv {} lower/{} \;
The -name parameter takes a glob, not a regular expression (those are both very useful pages). So the dot does not have a special meaning for this parameter - It is interpreted as a literal dot character. Also, in a regular expression the * means "0 or more of the previous expression" while in a glob it means "any number of any character." So, as others have pointed out, the following should get you any files below the current directory which start with an uppercase character:
find . -name '[A-Z]*'
If you want to find all the name beginning with a capital letter you have to use
find . -name "[A-Z]*"
NOT
find [A-Z].*
otherwise yo will try to locate all the file that begin with a capital letter and have a . just after

Ignore case when trying to match file names using find command in Linux

Right now, all I know to use is:
find / -name string.*
that is case sensitive and it won't find files named:
1string.x
STRing.x
string1.x
How can I search so that all the above would be returned in the search to a case-insensitive matching?
Use the -iname option instead of -name.
Or you could use find / | grep -i string
This works as well, if you want to avoid the single quotes:
find . -iname \*string\*
Use -iname in find for case insensitive file name matches.
If the system you are in does not have the find command provided by the GNU utils package, you can use the -name tag alone with POSIX bracket expressions as
find . -name '*[Ss][Tt][Rr]ing*'

Resources