How to use find exec cp with a regex pattern? - unix

I want to copy some files with string "ABC" in their name and without string "DEF" in their name using the find -exec command. This post mentions how to do it for the without case using find command. I want to know how to do it for both with and without cases.

You can use -and or -a for multiple true condition as follows. ! for negation can be applied after and
find . \( -regex ".*ABC.*" -and ! -regex ".*DEF.*" \) -exec cp {} /destination/folder/ \;

Related

BASH: performing a regex replace on a path from find command

AIM: to find all JS|TS excluding *.spec.js files in a directory but replace the base path with ./
I have this command
find src/app/directives -name '*.[j|t]s' ! -name '*.spec.js' -exec printf "import \"%s\";\n" {} \;
which in said directory prints the marked JS files. However I want to replace the src/app with ./
I've tried playing with [[]] and this command but they don't work.
find src/app/components -name '*.[j|t]s' ! -name '*.spec.js' -exec printf "import \"%s\";\n" ${{}/src
/hi} \;
zsh: bad substitution
Given your "AIM", all you really need is:
find src/app/directives -type f -name "*.[jt]s" ! -name "*.spec.js" -printf "./%f\n"
The reason being is the '|' in your character-class isn't matching anything, but isn't hurting anything for that matter. Your second ! -name "*.spec.js" is fine. You don't need -exec and can simply use -printf "./%f\n" (where "%f" provides the filename only for the current file). You simply prepend the "./" as part of the -printf format-string.
Let me know if I misunderstood your AIM or if you have further questions.
Removing src/app/directives While Preserving Remaining Path
If you want to preserve the remainder of the path after src/app/directives (essentially just replacing it with '.'), you can use a short helper-script with the POSIX parameter expansion to trim src/app/directives from the front of the string replacing it with '.' using printf in the helper script. For example the helper could be:
#!/bin/zsh
printf ".%s" "${1#./src/app/directives}"
(note: the leading "./" being removed along with src/app/directives is prepended by find, the '.' added by the printf format-string will result in the returned filename being ./rest/of/path/to/filename)
Call the script whatever you like, helper.sh below. Make it executable chmod +x helper.sh.
The find call would then be:
find src/app/directives -type f -name "*.[jt]s" ! -name "*.spec.js" -exec path/to/helper.sh '{}' \;
Give that a go and let me know if it does what you are needing.

Recursively remove portion of filename that matches a pattern

I'm on a UNIX system. Within a directory (and any of its subdirectories), I'm trying to rename all files that match a certain pattern:
change hello (1).pdf
to hello.pdf
Based on the top response from this question, I wrote the following command:
find . -name '* (1)*' -exec rename -ns 's/ (1)//' {} \;
The find works on its own and the rename also works on its own, but the above command only outputs Reading filenames from STDIN and does nothing. How can I make this work?
Figured this out! For whatever reason, it only works when you use the Perl version of rename like this:
find . -name '* (1)*' -exec rename -f -s ' (1)' '' {} \;

unix find command ending with '+' character

While perusing some AWS docs I noticed the following command:
find /var/www -type d -exec sudo chmod 2775 {} +
I'm familiar with the \; ending to exec in a find string but have never seen the '+'. Can anyone shed some light on this?
Here's the original page: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/install-LAMP.html
Thanks!
If you use a plus (+) instead of the escaped semicolon, the arguments will be grouped together before being passed to the command. For example:
$ find . -type f -exec echo {} +
. ./bar.txt ./foo.txt
In this case, only one child process (echo . ./bar.txt ./foo.txt)is created which is much more efficient, because it avoids a fork/exec for each single argument.
Using the escaped semi-colon, you will get a child process created for each argument.
$ find . -type f -exec echo {} \;
.
./bar.txt
./foo.txt

Recursively search files named string.xml for certain text

This command will search all directories and subdirectories for files containing "text"
grep -r "text" *
How do i specify to search only in files that are named 'strings.xml'?
You'll want to use find for this, since grep won't work that way recursively (as far as I know). Something like this should work:
find . -name "strings.xml" -exec grep "text" "{}" \;
The find command searches starting in the current directory (.) for a file with the name strings.xml (-name "strings.xml"), and then for each found file, execute the grep command specified. The curly braces ("{}") are a placeholder that find uses to specify the name of the file it found. More detail can be found in man find.
Also note that the -r option to grep is no longer necessary, since find works recursively.
You can use the grep command:
grep -r "text" /path/to/dir/strings.xml
grep supports an --include option whose use is to recurse in directories only searching file matching PATTERN. So, try something like below:
grep -R --include 'strings.xml' text .
I also tried using find which seems to be quite faster than grep:
find ./ -name "strings.xml" -exec grep "text" '{}' \; -print
These links speak about the same issue, might help you:
'grep -R string *.txt' even when top dir doesn't have a .txt file
http://www.linuxquestions.org/questions/linux-newbie-8/run-grep-only-on-certain-files-using-wildcard-919822/
Try below command
find . -type f | xargs grep "strings\.xml"
This will run grep "strings\.xml" on every file returned by find

Find/grep statement code filter

I need to generate a list of IFS files that contain a given string
("iim"). (IFS is the IBM System i database) I need to search directory /linoma/goanywhere/projects
recursively. I've been able to do this with a combination of the FIND
and GREP commands in QSHELL:
find /linoma/goanywhere/userdata/projects -type f -exec grep -lRF "iim"
'{}' ';'
Here's the rub: there is a subdirectory I want to ignore
(/linoma/goanywhere/userdata/projects/demo). How would I modify my
find/grep statement to exclude the demo folder?
find /linoma/goanywhere/userdata/projects -( -type f -and -not -path '/linoma/goanywhere/userdata/projects/demo/**' -) -exec grep -IRF 'iim' '{}' ';'
should work for GNU find, I believe. If your local find doesn't support that syntax, you might also brute-force remove by appending | grep -v /linoma/goanywhere/userdata/projects/demo

Resources