sed ack search / replace line break with string - linux

I have looked into a few SO threads, non of which have helped my specific situation.
I am trying to update a PHP app that I took over from php 5.6 to php 8.0
With that said there are MANY instances that look like:
<?
echo ...
function
I need to find all cases where <? is followed directly by a newline and replace it with <?php(newline)
Per the SO posts I've read .. I think I am coming close with the following:
find ./ -type f -readable -writable -exec sed -i ":a;N;$!ba;s/\<\?\n/\<\?php\n/g" {} \;
I think I am close .. But I can't figure out why it won't replace <?\n with <?php\n as the sed statement works without the newline. But per THIS POST it looks like I am doing it correctly.
What am I doing wrong?
Iterations I've tried:
$ find ./ -type f -readable -writable -exec sed -i ":a;N;$!ba;s/\<\?\n/\<\?php\n/g" {} \;
$ find ./ -type f -readable -writable -exec sed -i ":a;N;$!ba;s/<\?\n/<\?php\n/g" {} \;
$ find ./ -type f -readable -writable -exec sed -i ":a;N;$!ba;s/<?\n/<?php\n/g" {} \;
$ find ./ -type f -readable -writable -exec sed -i ":a;N;$!ba;s/<?\n\r/<?php\n/g" {} \;
$ find ./ -type f -readable -writable -exec sed -i ":a;N;$!ba;s/<?\r\n/<?php\n/g" {} \;

The sed command itself could be something as simple as:
sed -i 's/<?$/<?php/'
Glue that together with find and it might work for you.
$ is an anchor matching the end of a line, you might consider using ^ to anchor the match to the beginning as well:
s/^<?$/<?php/

Related

find and sed doesn't work in centos 7

I'm trying to find and replace a word in my entire project and I tried below versions of find and sed in centos 7 but nothing works.
find ./ -name "*.php" -exec sed -i '' s/mysql_/mysqli_/g \;
find ./ -name "*.php" -exec sed -i '' s/mysql_/mysqli_/g {} \;
find ./ -name "*.php" -exec sed -i '' 's/mysql_/mysqli_/g' {} \;
find ./ -name "*.php" -ls | xargs sed -i '' 's/mysql_/mysqli_/g'
sed: can't read s/mysql_/mysqli_/g: No such file or directory
All above commands giving me this error in loop even though I'm running these commands from the root of my project. Permissions are all correct. If I simply use find command alone it's working
find ./ -name "*.php" -ls (This Works)
I tried solutions available in stackoverflow but nothing works.
The fist pair of quotes in sed aren't necessary, try:
find ./ -name "*.php" -exec sed -i s/mysql_/mysqli_/g {} \;
The syntax is either -i'prefix' or --in-place='prefix', not -i 'prefix', since you added an space between the prefix and the argument, it's making sed use the prefix (empty string) argument as the regex and use the actual regex as a filename argument, which obviously won't find.
That's why you are getting the can't read s/mysql_/mysqli_/g: No such file or directory error.

How to pipe the results of 'find' to mv in Linux

How do I pipe the results of a 'find' (in Linux) to be moved to a different directory? This is what I have so far.
find ./ -name '*article*' | mv ../backup
but its not yet right (I get an error missing file argument, because I didn't specify a file, because I was trying to get it from the pipe)
find ./ -name '*article*' -exec mv {} ../backup \;
OR
find ./ -name '*article*' | xargs -I '{}' mv {} ../backup
xargs is commonly used for this, and mv on Linux has a -t option to facilitate that.
find ./ -name '*article*' | xargs mv -t ../backup
If your find supports -exec ... \+ you could equivalently do
find ./ -name '*article*' -exec mv -t ../backup {} \+
The -t option is a GNU extension, so it is not portable to systems which do not have GNU coreutils (though every proper Linux I have seen has that, with the possible exception of Busybox). For complete POSIX portability, it's of course possible to roll your own replacement, maybe something like
find ./ -name '*article*' -exec sh -c 'mv "$#" "$0"' ../backup {} \+
where we shamelessly abuse the convenient fact that the first argument after sh -c 'commands' ends up as the "script name" parameter in $0 so that we don't even need to shift it.
Probably see also https://mywiki.wooledge.org/BashFAQ/020
I found this really useful having thousands of files in one folder:
ls -U | head -10000 | egrep '\.png$' | xargs -I '{}' mv {} ./png
To move all pngs in first 10000 files to subfolder png
mv $(find . -name '*article*') ../backup
Here are a few solutions.
find . -type f -newermt "2019-01-01" ! -newermt "2019-05-01" \
-exec mv {} path \;**
or
find path -type f -newermt "2019-01-01" ! -newermt "2019-05-01" \
-exec mv {} path \;
or
find /Directory/filebox/ -type f -newermt "2019-01-01" \
! -newermt "2019-05-01" -exec mv {} ../filemove/ \;
The backslash + newline is just for legibility; you can equivalently use a single long line.
xargs is your buddy here (When you have multiple actions to take)!
And using it the way I have shown will give great control to you as well.
find ./ -name '*article*' | xargs -n1 sh -c "mv {} <path/to/target/directory>"
Explanation:
-n1
Number of lines to consider for each operation ahead
sh -c
The shell command to execute giving it the lines as per previous condition
"mv {} /target/path"
The move command will take two arguments-
1) The line(s) from operation 1, i.e. {}, value substitutes automatically
2) The target path for move command, as specified
Note: the "Double Quotes" are specified to allow any number of spaces or arguments for the shell command which receives arguments from xargs

Find and exec command in linux. Is it possible to pipe 2 find and exec commands

I'm trying to accomplish this task
1) Find directory A (DIR_A) and copy all files in the directory(including its sub-directory, if any) into a new directory called DIR_B
2) In directory (DIR_B),replace the word apple with orange
I executed the following code and for some reason, it copies all the files but it fails on the second task (replace apple with orange). I would appreciate help on this. Below is my code
find DIR_A -iname FILEA -type f -exec cp {} DIR_B \;|find DIR_B/ -iname \*.* -type f -exec sed -i "s|apple|orange|g" {} \;
Rather than trying to piping the output from one find into the other, why not just run them sequentially? I'm not sure that find reads from its stdin.
find DIR_A -iname FILEA -type f -exec cp {} DIR_B \; ; find DIR_B/ -iname \*.* -type f -exec sed -i "s|apple|orange|g" {} \;
I've replaced your pipe with a semi-colon.
Try this :
Sed Syntax :
sed 's/old/new/g'
find DIR_A -iname FILEA -type f -exec cp {} DIR_B \;|find DIR_B/ -iname \*.* -type f -exec sed -i "s/apple/orange/g" {} \;

Linux find and replace

How can I replace "abc" with "abcd" on all files of a folder using shell?
Is it possible using sed command?
Try the following command for the file file.txt:
sed -i 's/abc/abcd/g' file.txt
Try the following command for all files in the current folder:
find . -maxdepth 1 -type f -exec sed -i 's/abc/abcd/g' {} \;
For the files in the current directory and all subdirectories:
find . -type f -exec sed -i 's/abc/abcd/g' {} \;
Or if you are fan of xargs:
find . -type f | xargs -I {} sed -i 's/abc/abcd/g' {}
sed -i 's/abc/&d/g' *
should work.
Yes:
find /the/folder -type f -exec sed -i 's,\<abc\>,&d,g' {} \;

How do I do a recursive, in-file replace?

Let's say I want to scan through every file in this directory (recursive, too).
And I want to replace happy.magic with sad.apps.magic
How can I do that?
find . -type f -exec sed -i 's,happy.magic,sad.apps.magic,g' {} \;
Eric is right, but just to be clear:
find ./ -type f -exec sed -i "s/happy\.magic/sad\.apps\.magic/g" {} \;

Resources