GNU find and more complex -exec option parameter values - find

This works for me:
$> find . -name "*.log" -exec basename '{}' \;
20160114.log
20160115.log
20160116.log
20160117.log
20160118.log
Is the {}, \ and ';' mandatory when using -exec as any other syntax simply doesn't work?
The following, more complex example doesn't work:
$> find . -name "*.log" -exec echo $(basename '{}') \;
./log/20160114.log
./log/20160115.log
./log/20160116.log
./log/20160117.log
./log/20160118.log
echo here is just to demonstrate. I eventually plan to use something like rm $TARGET_DIR/$(basename '{}') in its placeā€¦ It just doesn't work that way (nesting). Any ideas?

Related

unix code inside perl

This is the code:
#!/usr/bin/perl -w
$dir="/vol.nas/rpas_qc/mohima/Test/translations";
$dir1="/vol.nas/rpas_qc/mohima/Test/dest";
`find $dir -type f -exec rsync -a {} $dir1\`;
This line:
find $dir -type f -exec rsync -a {} $dir1\
works fine in Unix but I am getting an error in perl:
Can't find string terminator "`" anywhere before EOF at test1.pl line 4
I am trying to copy all files in $dir to $dir1 without the subdirectories.
Using perl since the script will do lot of other stuff which is easier in perl.
Any help is appreciated.
\ is the escape character in Perl. The \ at the end of your find command is escaping the `. You need to escape the backslash with another one.
`find $dir -type f -exec rsync -a {} $dir1 \\`;
This will now fail with find: missing argument to -exec. You're also going to need a semicolon on the end of the -exec part.
`find $dir -type f -exec rsync -a {} $dir1 \\;`;
In perl, try changing:
find $dir -type f -exec rsync -a {} $dir1\
To:
find $dir -type f -exec rsync -a {} $dir1\\
You need to escape your backslash and special characters. Once for Perl code and again for whatever other language (in this case your shell).
`find $dir -type f -exec rsync -a {} $dir1\`;
In the above code, the \ is escaping your last backtick ( ` ) in perl. So your child shell execution is never terminated. To fix this simply add another backslash, which escapes that character from being interpolated:
`find $dir -type f -exec rsync -a {} $dir1\\`;

Escape the current file name "{}" of shell find -exec in the subcommand result "$()"?

I want to run something like:
find . -type files -exec echo "touch -cmd '"$(date --utc -r '{}' +"%Y-%m-%d %H:%M:%S.%N +0000")"' "$(ls --quoting-style=shell '{}')
It doesn't seem to work since "{}" doesn't seem to be expanded in the $(). How could I do to make it work right?
Simplify your problem.
Write a shell script, and then get the shell script working. Then execute your shell script using find.
find . -type files -exec myScript '{}'

Find all emails in files and replace with specific email

How can I find all emails in php files and replace with an email?
find . -iname '*.php' -exec grep -E -o "\b[a-zA-Z0-9.-_]+#[a-zA-Z0-9.-]+\.[a-zA-Z]+\b" -exec sed -i 's//email#domain.com/g' {} \;
Find emails in php files command is:
find . -iname '*.php' -exec grep -E -o "\b[a-zA-Z0-9.-_]+#[a-zA-Z0-9.-]+\.[a-zA-Z]+\b" {} \;
and replace command is:
find . -iname '*.php' -type f -exec sed -i 's/old-email#domain.com/new-email#domain.com/g' {} \;
But I don't know exactly how to join them in one command.
Any ideas?

Using Sed and Find with Grep Linux

I am writing a script that will saech for php files that contain a phrase and I would like that phrase replaced with a new one below is my little script but it is not working it searches ok but does not work with the search and replace section
find . -type f -name "*.php" -exec grep -H "define('DB_HOST', 'localhost');" {} \; | xargs sed -i "define('DB_HOST', 'localhost');/define('DB_HOST', '10.0.0.1');/g"
can someone explain to me what i am doing wrong
many thanks
Joe
did you forget the 's/' at the beggining of the sed expression? As in
sed 's/expression1/expression2/g'
You seem to have
sed 'espression1/expression2/g'
Edit
Another thing: You don't need to use xarg here. You can use multiple -exec flags - and it will to each only if all the previous succeeded:
find . -name '*.php' -exec grep 'whatever' {} \; -exec sed -i 's/whatever/you want/g' {} \;
This will work:
find . -type f -name "*.php" -exec grep -l "define('DB_HOST', 'localhost');" {} \; | xargs sed -i "s/define('DB_HOST', 'localhost');/define('DB_HOST', '10.0.0.1');/g"
Corrections
Missing s/ in sed search and replace command
use grep -l instead of grep -H

find using multiple name patterns

I have this working fine for me:
find Sources/$1-$2 -name '*' |xargs perl -pi -e "s/domain.com/$2/g"
But when I change it to the following it doesn't:
find Sources/$1-$2 -name '*.php,*.rb' |xargs perl -pi -e "s/domain.com/$2/g"
What wrong?
Here's some explanation behind the solution that others have provided.
The tests in a find command are combined with Boolean operators:
-a -and
-o -or
! -not
If you don't supply an operator, -and is the default.
find . -type f -name '*.rb' # The command as entered.
find . -type f -a -name '*.rb' # Behind the scenes.
Your search failed because it didn't find any matching files:
# Would find only files with bizarre names like 'foo.php,bar.rb'
find . -name '*.php,*.rb'
You need to supply the file extensions as separate -name tests, combined in an OR fashion.
find . -name '*.php' -o -name '*.rb'
you have to write it as:
find Sources/$1-$2 -name '*.php' -o -name '*.rb' ....
I'm guessing that you want all files then end in .php and .rb.
Try find Sources/$1-$2 \( -iname "*.php" -o -iname "*.rb" \) -print |xargs perl -pi -e "s/domain.com/$2/g"
It is much better filtering out find's result with [ef]grep. Why?
Because you can fed the grep pattern as an argument, or can read it from the config or soo. It is much easier to write: grep "$PATTERN" as constructing long find arguments with '-o'. (ofc, here are situations, where find args are better), but not in your case.
The cost is one more process. So, for you example is easy to write a script myscript.sh
find Sources/$1-$2 -print | egrep -i "$3" | xargs ...
you can call it
./myscript.sh aaa bbb ".(php|rb)$"
and the result will equivalent to more complicated
find Sources/$1-$2 \( -iname '*.php' -o -iname '*.rb' \) | xargs ...
but
why bother? If you have bash4+, (and shopt -s globstar in your .bashrc) you can simple write:
perl -pi -e '.....' Sources/aaa-bbb/**/*.{rb,php}
the ** is like a find -name.
By the way, xargs is not needed here.
find Sources/$1-$2 \( -name '*.php' -o -name '*.rb' \) \
-exec perl -i -pe "s/domain\.com/$2/g" {} +
Also notice the "." in /domain.com/ needs to be escaped.