How to I search for a text string and copy those files to another directory - unix

I need to find a text string within some files. This will give me a list:
find . -type f -print0 | xargs -0 grep -il "google"
then I need to copy those files to a folder and rename them. So I think I need to pipe them again to something like this
| xargs -0 -n1 -I '{}' cp '{}' ../testTarget/{}_RECOVERED
Alas:
find . -type f -print0 | xargs -0 grep -il "google" |
xargs -0 -n1 -I '{}' cp '{}' ../testTarget/{}_RECOVERED
Results: cp: {}: No such file or directory
Please advise
the filenames have space and commas in them (Dovecot)

find . -type f -print0 | xargs -0 grep -lh "google" | xargs -I % cp % ../testTarget/%_RECOVERED
or
find SOURCE/ -type f -print0 | xargs -0 grep -lh "SEARCH_STRING" | xargs -I % cp % TARGET_DIR/%_RECOVERED

for i in `ls -1tr`
{
SEARCH_STRING_LINE_NO=`grep -n SEARCH_STRING i | cut -d: -f1`;
if [ SEARCH_STRING_LINE_NO > 0 ] then
cp i folder_path_where_u_want_to_copy
fi
}
Replace SEARCH_STRING with the text string you want to find.
Replace folder_path_where_u_want_to_copy with the folder path where u want to move the files containing SEARCH_STRING
This should copy the files containing SEARCH_STRING to the folder folder_path_where_u_want_to_copy
I have not tested this code as I dont have a unix box with me right now, but atleast it should give u an idea to approach

The following command will grep for pattern and copy the files to your desired location.
find /path/to/search -type f -exec grep -q "pattern" '{}' ';' -exec cp '{}' /path/to/copy ';'
Once the files are copied over you can use rename command to rename them accordingly.

Related

pdftotext find command returning No Such File or Directory

I'm using pdftotext and find to find the contents of a PDF file and move it. I can find all of the files, but trying to add the mv command to the end with xargs returns "No such file or directory" for each file.
My code is as follows:
find ./ -name '*.pdf' -exec sh -c 'pdftotext "{}" - | grep -l -Z -i --with-filename --label="{}" --color "Thank you" | xargs -0 -I{} mv {} Found/' \;
Is xargs not getting the correct file path? I'm not sure what is happening.
you can get this, when the names contain spaces. Could you try this.
find ./ -name '*.pdf' -not -path "./Found/*" -exec sh -c 'pdftotext "{}" - | grep -l -Z -i --with-filename --label="{}" --color "Thank you"' \; | xargs -0 -I{} mv {} ./Found/

Is there any way to parellelly grep through bz2 files

I recently found out this solution to less through compressed gz files parellelly based on the cores available.
find . -name "*.gz" | xargs -n 1 -P 3 zgrep -H '{pattern to search}'
P.S. 3 is the number of cores
I was wondering if there was a way to do it for bz2 files as well.
Currently I am using this command:
find -type f -name '*.bz2' -execdir bzgrep "{text to find}" {} /dev/null \;
Change *.gz to *.bz2; change zgrep to bzgrep, and there you are.
For a bit of extra safety around unusual filenames, use -print0 on the find end and -0 on the xargs:
find . -name "*.bz2" -print0 | xargs -0 -n 1 -P 3 bzgrep -H '{pattern to search}'

Need help in unix find with xargs command

Am trying to delete files with below find command, few files are not deleting and all those file names are like: filname.123.log.
I can't rename or can't do any thing on file name just need to delete
command
$ find /BASE/CODE/LOGS_BACK -type f -mtime +60 | xargs rm -f
xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option
I googled and try with the below command but it is giving different error.
$ find /BASE/CODE/LOGS_BACK -type f -mtime +60 | xargs -0 rm -f
xargs: argument line too long
Can you please help regarding this?
using -0 option in xargs means using -print0 option in find :
find /BASE/CODE/LOGS_BACK -type f -mtime +60 -print0 | xargs -0 rm -f
Then all results of find will be ended with '\0' NUL char and xargs will regenerate list correctly by parsing with same char.
find can directly execute a command for each result:
$ find /BASE/CODE/LOGS_BACK -type f -mtime +60 -exec rm -f {} \;
{} is replaced with each matching filename. \; end the command.
This is the fastest way to achieve what you want:
find /BASE/CODE/LOGS_BACK -type f -mtime +60 -exec rm -f {} +
Note the ending + which does the same job as xargs.

Removing Files with specific ending. Need something more specific

I'm trying to purge all thumbnails created by Wordpress because of a CMS switchover that I'm planning.
find -name \*-*x*.* | xargs rm -f
But I dont know bash or regex well enough to figure out how to add a bit more specifity such as only the following will be removed
All generated files have the syntax of
<img-name>-<width:integer>x<height:integer>.<file-ext> syntax
You didn't quote or escape all your wildcards, so the shell will try to expand them before find executes.
Quoting it should work
find -name '*-*x*.*'| xargs echo rm -f
Remove the echo when you're satisfied it works. You could also check that two of the fields are numbers by switching to -regex, but not sure if you need/want that here.
regex soultion
find -regex '^.*/[A-Za-z]+-[0-9]+x[0-9]+\.[A-Za-z]+$' | xargs echo rm -f
Note: I'm assuming img-name and file-ext can only contain letters
You can try this:
find -type f | grep -P '\w+-\d+x\d+\.\w+$' | xargs rm
If you have spaces in the path:
find -type f | grep -P '\w+-\d+x\d+\.\w+$' | sed -re 's/(\s)/\\\1/g' | xargs rm
Example:
find -type f | grep -P '\w+-\d+x\d+\.\w+$' | sed -re 's/(\s)/\\\1/g' | xargs ls -l
-rw-rw-r-- 1 tiago tiago 0 Jun 22 15:14 ./image-800x600.png
-rw-rw-r-- 1 tiago tiago 0 Jun 22 15:17 ./test 2/test 3/image-800x600.png
The below GNU find command will remove all the files which contain this <img-name>-<width:integer>x<height:integer>.<file-ext> syntax string. And also i assumed that the corresponding files has . in their file-names.
find . -name "*.*" -type f -exec grep -l '<img-name>-<width:integer>x<height:integer>.<file-ext> syntax' {} \; | xargs rm -f
Explanation:
. Directory in which find operation is going to takeplace.(. represnts your current directory)
-name "*.*" File must have dot in their file-names.
-type f Only files.
-exec grep -l '<img-name>-<width:integer>x<height:integer>.<file-ext> syntax' {} print the file names which contain the above mentioned pattern.
xargs rm -f For each founded files, the filename was fed into xargs and it got removed.

How to use find command to find all files with extensions from list?

I need to find all image files from directory (gif, png, jpg, jpeg).
find /path/to/ -name "*.jpg" > log
How to modify this string to find not only .jpg files?
find /path/to -regex ".*\.\(jpg\|gif\|png\|jpeg\)" > log
find /path/to/ \( -iname '*.gif' -o -iname '*.jpg' \) -print0
will work. There might be a more elegant way.
find -E /path/to -regex ".*\.(jpg|gif|png|jpeg)" > log
The -E saves you from having to escape the parens and pipes in your regex.
find /path/to/ -type f -print0 | xargs -0 file | grep -i image
This uses the file command to try to recognize the type of file, regardless of filename (or extension).
If /path/to or a filename contains the string image, then the above may return bogus hits. In that case, I'd suggest
cd /path/to
find . -type f -print0 | xargs -0 file --mime-type | grep -i image/
find /path -type f \( -iname "*.jpg" -o -name "*.jpeg" -o -iname "*gif" \)
On Mac OS use
find -E packages -regex ".*\.(jpg|gif|png|jpeg)"
In supplement to #Dennis Williamson 's response above, if you want the same regex to be case-insensitive to the file extensions, use -iregex :
find /path/to -iregex ".*\.\(jpg\|gif\|png\|jpeg\)" > log
find -regex ".*\.\(jpg\|gif\|png\|jpeg\)"
in case files have no extension we can look for file mime type
find . -type f -exec file -i {} + | awk -F': +' '{ if ($2 ~ /audio|video|matroska|mpeg/) print $1 }'
where (audio|video|matroska|mpeg) are mime types regex
&if you want to delete them:
find . -type f -exec file -i {} + | awk -F': +' '{ if ($2 ~ /audio|video|matroska|mpeg/) print $1 }' | while read f ; do
rm "$f"
done
or delete everything else but those extensions:
find . -type f -exec file -i {} + | awk -F': +' '{ if ($2 !~ /audio|video|matroska|mpeg/) print $1 }' | while read f ; do
rm "$f"
done
notice the !~ instead of ~
Adding -regextype posix-extended option only worked in my case:
sudo find . -regextype posix-extended -regex ".*\.(css|js|jpg|jpeg|png|ico|ttf|woff|svg)" -exec chmod 0640 {} \;

Resources