Linux Command: Find & Replace using regex not woking as expected - regex

I am trying to replace a path in all php files using regex command, but it isn't working as expected!
I want to replace '/home/example/public_html with $_SERVER['DOCUMENT_ROOT'] . '
I am using the below command in ssh:
find /var/www/advertise/ -name '*.php' -type f -exec sed -i 's/\'\/home\/example\/public_html/\$\_SERVER\[\'DOCUMENT\_ROOT\'\]\ \.\ \'/g' {} \;
When i enter the command and hit return, > sign follows like:
>
>
>
.. so on as i keep hitting return to execute the command.
Where as below command works perfectly (for replacing home/example/public_html with var/www):
find /var/www/advertise/ -name '*.php' -type f -exec sed -i 's/home\/example\/public_html/var\/www/g' {} \;

You're messing up with the quotes.
Use a separator other than / so that you don't need to escape the /
You don't need to escape in the replacement
Since you have ' in the replacement, better use "s#..#..#" (i.e. double quotes). However, you'll need to escape the $ in the replacement to prevent the shell from trying to expand.
The following might work for you:
find /var/www/advertise/ -name '*.php' -type f -exec sed -i "s#'/home/example/public_html#\$_SERVER['DOCUMENT_ROOT'] . '#g" {} \;

Related

Strip unwanted characters from a series of text files

Hi I've got a list of csv files which need to be formatted properly by getting rid of some unwanted characters.
original:
9: ["2019-4-24",-7.101458109105941]
10: ["2019-5-6",-7.050609022950812]
100: ["2019-5-6",-7.050609022950812]
I'd like to modify as:
2019-4-24,-7.101458109105941
2019-5-6,-7.050609022950812
2019-5-6,-7.050609022950812
There are dozens of files in this format and I was thinking of writing a sed command which makes a series of null substitutions for all the files in directory, but these don't seem to work.
find ./ -type f -exec sed -i '' -e "s/^[[:space:]]*//" {} \;
find ./ -type f -exec sed -i '' -e "s/\[//" {} \;
find ./ -type f -exec sed -i '' -e "s/\]//" {} \;
Many thanks for suggestions.
I found this to work on my linux machine.
find ./ -type f -exec sed -i "s/^.\+\[//;s/\"//g;s/\]//" {} \;
Which, from what I gather is equivalent to the following in macOS:
find ./ -type f -exec sed -i '' "s/^.\+\[//;s/\"//g;s/\]//" {} \;
It comprises of 3 substitutions(separated by semicolon):
s/^.\+\[// deletes everything from the start to the "[" character.
s/\"//g deletes all occurences of the double quote character.
s/\]// deletes the final "]" at the end.
And please make a backup or something if you are going to use sed -i.

Find and rename files/folders using regex

I am trying to find a right regex for the filename that starts with I0[0-9][0-9]- eg: "I097-". I am not familiar with regex but using online, I came up with this [I][0][\d][\d][-], I am sure this is not the best regex pattern for the string I have, but I tested using online regex tools and it works. Now I want to use Linux 'find' to find all the files that match this regex and re-name the resulting files by replacing the matching string with nothing.
From:
I071-PTEN-7
./I071-PTEN-7/I071-PTEN-7.txt
To:
PTEN-7
./PTEN-7/PTEN-7.txt
command used:
find . -name "I0*" -type f -o -name "I0*" -type d -exec rename -n "s/[I][0][\d][\d][-]/''/" {} \;
But it doesn't seem to do anything, not sure what is going on. Any help to find the issue or solution would be greatly appreciated. Thanks.
Use -execdir option to get only filenames entries in find also there is no need to use character class around every character in your regex.
find . -name 'I0*' -execdir rename -n 's/^I0\d\d-//' {} \;
If rename isn't working then you may try this:
find . -type f -name 'I0*' -execdir bash -c 'mv "$1" "${1/I0[0-9][0-9]-/}"' - {} \; &&
find . -name 'I0*' -execdir bash -c 'mv "$1" "${1/I0[0-9][0-9]-/}"' - {} \;

How to -find -exec cp files from a list containing a portion of the filename

I've been searching for a long time and can't find an answer that works. I have a list with partial filenames (the first few letters of the filenames). If I place the file names individually as follows it works:
find ~/directory/to/search -name "filename*" -print -exec cp '{}' ~/directory/to/copyto \;
If I try to include the list in this scenario it does not:
cat ~/directory/List.txt | while read line
do
echo "Text read from file - $line"
find ~/directory/to/search -name "$line*" -type f
done
neither does this:
cat ~/directory/List.txt | while read line
do
echo "Text read from file - $line"
find ~/directory/to/search -name "$line&*" -type f
done
Ultimately, I'd like to add:
-exec cp '{}' ~/directory/to/copy/to \;
And copy over all files matching the find criteria.
I've tried using grep but the files are huge so it would take forever. I tried using all sorts of combinations of find, xargs, cp, grep and regex as read in previous searches and no luck.
Is the only solution to write a long script with a bunch of if then statements? I've been using Linux but it would be cool to use it on mac as well.
Here is a crude attempt at getting away with a single find invocation.
predicates=()
or=''
while read -r line; do
predicates+=($or -name "$line*")
or="-o"
done < ~/directory/list.txt
find ~/directory/to/search -type f \( "${predicates[#]}" \) \
-exec cp -t ~/directory/to/copy/to {} +
The array functionality requires an extended shell (Bash, ksh, etc) with this functionality; it won't work with /bin/sh.
cp -t is a GNU extension; if you don't have that, maybe just use your original -exec cp {} dir \; though it will be less efficient. Some old versions of find also don't support -exec ... +.

Mac: replace text inside files in directory using regular expression

I need to replace all matches (regular expression) in directory from "*::" to be "\*::"
examples: (in multiple php files)
ID::
user::
process::
....
to be:
\ID::
\user::
\process::
I currently use,single commands
find . -type f -name '*.php' -exec sed -i '' s/ID::/\\\\ID::/ {} +
find . -type f -name '*.php' -exec sed -i '' s/user::/\\\\user::/ {} +
find . -type f -name '*.php' -exec sed -i '' s/process::/\\\\process::/ {} +
how to write regular expression to replace any "*::" => "\*::"
thanks,
You want to use "grouping" or "back-referencing" to refer back to a portion of the regular expression. This is done by surrounding the intended group with \( and \), and referring back to them with \1, \2, etc. In your case, the following expression should work:
$ echo -e "ID::\nuser::\nprocess::" | sed 's/\(.*\)::/\\\1::/g'
with the following output:
\ID::
\user::
\process::
I update "bebop" solution to meet my requirements, alot of thanks to him
solution:
sed -i -e 's/\([A-Za-z]*\)::/\\\1::/g' `grep -ril '::' *.php`

Bash script find/sed not working

I have the following line in my bash script:
find . -name "*.html" -print |
xargs sed -i 's/http\:\/\/version2\.staging\.myname\.com//g'
and it's giving me the following error:
sed: 1: "./instant/index. ...": invalid command code .
What I'm trying to do is replace any occurrence of http://version2.staging.myname.com with /. How do you do it?
Usually I use something like:
find . -name "*.html" -exec sed -i 's|http://version2\.staging\.myname\.com/|/|g' '{}' ';'
To test this out, you can first insert an echo statement
find . -name "*.html" -exec echo sed -i 's|http://version2\.staging\.myname\.com/|/|g' '{}' ';'
... that will tell you if the output will be what you expect. I always recommend doing a dry-run with echo first before any mass update. Also you can use | as an alternate regex delimiter to avoid using as many `/' in the paths.
For OSX try this:
find . -name "*.html" -exec sed -i.bak 's#http://version2\.staging\.myname\.com##g' '{}' \; -print
I think you may be using a Mac (and now I see a comment that you are on an iMac). On Mac OS X, the sed -i option requires an argument. That makes sense of your error message. The sed command is interpreting your s/...//g command as the suffix to use for the back up file; it is then trying to interpret the first file name as the sed script, and fortunately, that is not working.
Additionally, you can avoid most of the escaping issues by using some character other than / as the delimiter for s///. Also, it is generally better (especially on Macs where file paths often end up with spaces in them) to avoid xargs and use -exec in find, along with the + option to do what xargs does — namely group many file names into one command invocation.
This leads to:
find . -name "*.html" -type f \
-exec sed -i .bak -e 's%http://version2.staging.myname.com%%g' {} +
(NB: strictly, that will map http://version2-staging*myname#com to / too; if you're really worried about that, by all means escape the dots in the URL.)
If you want to get rid of the .bak files afterwards:
find . -name '*.bak' -type f -exec rm -f {} +