How to find files which contains preferred character in Linux - linux

How can I find files and directories which contains one character for example "a"
I know that there is command ls a* but this find all files which starts with character

Try the find command to copy files which begin with the "a" character.
find /your/source/path -name 'a*' -exec cp {} /your/target/path \;
To find files which contain the "a" character use the following command.
grep -r 'a' /your/source/path/* | xargs cp /your/target/path

As the others have mentioned,
find . -name '*a*'
should do what you are looking for.
However, note that this only looks for lowercase 'a'. If you want it to be case insensitive you can use
find . -iname '*a*'
The '*' is a wildcard and means that it matches any random selection of text. If for example you had instead written
find . -name 'a'
'find' will only find files with the name 'a', without any extensions.
Thus,
find . -name '*a'
will find all files ending with the letter 'a', while
find . -name 'a*'
will find all files starting with the letter 'a'.

find [root_of_the_search] -name [pattern]
for example
find . -name "*a*"
you can copy them like this
cp `find . -name "a"` /destination/path

Related

List files that start with one or two numeric characters and a dash [duplicate]

This question already has answers here:
use find to match filenames starting with number
(3 answers)
Closed 1 year ago.
I want to select all the files in the current folder that start with either one or two numerical character.
e.g.:
1- filenameA
2- filenameB
....
17- filenameT
18- filenameU
I would like to know how I select only the files that start with up to 2 numerical characters.
So far I have tried
$ find . -name '[0-9]{1,2}*'
But it doesn't return anything, which I don't understand why. My reasoning when writing this command was:
[0-9] select any string starting with a number from 0 to 9
{1,2} and this can be repeated 1x or 2x
What am I getting wrong?
my INelegant solution so far
run the below two commands to tackle first the [0-9] range and then [10-99] range
$ find . -name '[0-9]-*'
$ find . -name '[0-9][0-9]-*'
You don't need find for that.
$ touch 7-foo 42-bar 69-baz
$ printf '%s\n' [0-9]{,[0-9]}-*
7-foo
42-bar
69-baz
$ shopt -s nullglob
$ printf '%s\n' {0..99}-*
7-foo
42-bar
69-baz
You can use gnu find like this with -regex option:
find . -maxdepth 1 -type f -regex '.*/[0-9][0-9]?-.*'
Details:
-maxdepth 1: In current directory only
-type f: Match files only
-regex '.*/[0-9][0-9]?-.*': Match 1 or 2 digits in filename at the start before matching a -
If you don't have gnu find then you may use:
find . -maxdepth 1 -type f \( -name '[0-9][0-9]-*' -o -name '[0-9]-*' \)
In your initial code, you are trying to use a regular expression where find's -name is expecting you to use shell pattern matching notation.
Your original "INelegant solution" using -name '[0-9]*' will fail because [0-9]* matches all files starting with a digit not just those with only one digit. Your updated solution should work better and can be written as a single command:
find \( -name '[0-9]-*' -o -name '[0-9][0-9]-*' \) ...
Alternatively, with POSIX find, you could search for filenames that start with a digit but exclude any whose third character is a digit:
find . -type f -name '[0-9]*' ! -name '??[0-9]*'
To not descend into sub-directories is slightly complicated if your find does not have -maxdepth option:
find . ! -name . -prune -type f -name '[0-9]*' ! -name '??[0-9]*'
! -name . matches everything except the starting directory. Applying -prune to them avoids the sub-directory descent.

[linux find cmd]: limit the find command to search directories matching a given word or regex

Can I limit the find command to search directories matching a given regex only?
I looked at
$ man find
but couldn't find any --include-directories option.
Using RHEL GNU/Linux.
Thanks.
One way you can try is :
find . ! \( -name . -o -regex ".*/dir" \) -prune -name file
The problem for this solution is you have to include starting directory (. in this case)
-prune means to exclude all directories except . or .*/dir

Exclude range of directories in find command

I have directory called test which has sub folders in the date range like 01,02,...31. This all sub folders contain .bz2 files in it. I need to search all the files with .bz2 extension using find command but excluding particular range of directories. I know about find . -name ".bz2" -not -path "./01/*", but writing -not -path "./01/*" would be so pathetic if I would want to skip 10 directories. So how would I skip 01..19 subdirectories in my find command ?
You can use wildcards in the pattern for the option -not -path:
find ./ -type f -name "*.bz2" -not -path "./0*/*" -not -path "./1*/*
this will exclude all directories starting with 0 or 1. Or even better:
find ./ -type f -name "*.bz2" -not -path "./[01]*/*"
Firstly, you can help find by using -prune rather than -not -path - that will avoid even looking inside the relevant directories.
To your main point - you can build a wildcard for your example (numeric 01 to 19):
find . -path './0[1-9]' -prune -o -path './1[0-9]' -prune -o -print
If your range is less convenient (e.g. 05 to 25) you might want to build the range into a bash variable, then interpolate that into the find command:
a=("-path ./"{05..25}" -prune -o")
find . ${a[*]} -print -prune
(you might want to echo "${a[*]}" or printf '%s\n' ${a[*]} to see how it's working)
For me, I found the find command as a standalone tool somehow cumbersome. Therefore, I always end up using a combination of find just for the recursive file search and grep to make the actual exculsion/inclusion stuff. Finally I hand over the results to a third command which will perform the actions, like rm to remove files for example.
My generic command would look something like this:
find [root-path] | grep (-v)? -E "cond1|cond2|...|condN" | [action-performing-tool]
root-path is where to start the search recursively
add -v option is used to invert the matching results.
cond1 - condN, the conditions for the matching. When -v is involed then this are the conditions to not match.
the action-performing-tool does the actual work
For example you want to remove all files not matching some conditions in the current directory:
find . -not -name "\." | grep -v -E "cond1|cond2|cond3|...|condN" | xargs rm -rf
As you can see, we are searching in the current directory indicated by the dot as root-path: then we want to invert the matching results, because we want all files not matching our conditions: and finally we pass all files found to rm in order to delete them: I add -rf to recursive/force delete all files. I used the find command with -not -name "." to exclude the current directory indicated normally by dot.
For the actuall question: Assume we have a directory using .git and .metadata directory and we want to exclude them in our search:
find . -not -name "\." | grep -v -E ".git|.metadata" | [action-performing-tool]
Hope that helps!
If you wan to exclude child directory under parent directory then this might be useful:
E.g.- You have parent directory "ParentDir" and it has two child directories "Child1, Child2". You wan to read files from "Chiled2" only and skip "Child1". Then this will help.
find ./ParentDir ! -path "./ParentDir/Child1*" -name *.<extention>

find command search pattern

I have below 4 files
a_ROLLBACK2to3__test.sql,
a_1to2__test.sql,
a_2to3__test.sql,
a_2to2__test.sql
I want to write a find command to return the files a_1to2__test.sql, a_2to3__test.sql and a_2to2__test.sql, the file a_ROLLBACK2to3__test.sql should not be included in the search.
my find command looks like
find . -name "*_*to*__*.sql"
but this returns all files but I don’t want a_ROLLBACK2to3__test.sql.
basically the files with ROLLBACK after the first _ should not be included..
Can anyone help me to write the search pattern for my requirement?
Thanks
Simply filter the results with grep:
find . -name '*_*to*__*.sql' | grep -v ROLLBACK
Or use the AND clause -a with negation !:
find . -name '*_*to*__*.sql' -a ! -name '*ROLLBACK*'
You could simply look for the underscore followed by a digit:
find . -name '*_[0-9]*to*__*.sql'
or for an underscore not followed by R:
find . -name '*_[!R]*to*__*.sql'

How to remove all files NOT ending with certain formats?

So to remove all files ending with .lnx, the cmd would be rm *.lnx, right?
If I want to remove all files that do NOT end with [.lnx], what command should I use?
Is there such a thing?
You can use this:
$ rm !(*.lnx)
!(pattern-list)
Matches anything except one of the given patterns.
A pattern-list is a list of one or more patterns separated by a ‘|’.
find . -depth 1 -type f -not -name '*.lnx' -delete
find all files (-type f) in the current directory (-depth 1) which do not match the filename (-not -name '*.lnx'), and delete them (-delete)
As always, test this first. Run it without the -delete to see all the files that match.
ls | grep -v '\.lnx$' | xargs rm

Resources