I am in need to find and replace a part of text in all my files on my web server. I am aware of the command (by Google'ing it) as
find . -type f -exec sed -i 's/foo/bar/g' {} +
Problem though is that the text I need to replace contains / in it. For instance I need to...
Find
/home/this/root/
With
/home/that/root/
since the command above uses / as a separator to determine find/replace how do I include / in my search so the command does not get confused?
Use a different sed delimiter.
find . -type f -exec sed -i 's~foo~bar~g' {} +
Related
I am looking for a quick command to search all .htaccess files for a specific IP address and change it to another IP address from the command line
something like
grep -rl '255.255.254.254' ./ | xargs sed -i 's/254/253/g'
I know the above example is a bad way to do it, just an example (and showing I did some searching to find a solution
Search: files with filename .htaccess (within 2 levels deep of current path?)
Find: 255.255.254.254
Replace with: 255.255.253.253
or, is this too much to ask of my server and I would be better off replacing them as I find them?
Try:
find . -type f -name '.htaccess' -execdir sed -i 's/255\.255\.254\.254/255.255.253.253/g' {} +
How it works:
find .
Start looking for files in the current directory.
-type f
Look only for regular files.
-name '.htaccess'
Look only for files named .htaccess.
-execdir sed -i 's/255\.255\.254\.254/255.255.253.253/g' {} +
For any such files found, run this sed command on them.
Because . is a wildcard and you likely want to match only literal periods, we escape them: \.
We use -execdir rather than the older -exec because it is more secure against race conditions.
I need to recursively replace a string in some files but I cannot get it to work for my particular string(s).
If I use something simple like:
find . -type f -exec sed -i 's,functions,functions2,g' {} \;
Then this works fine but if I use:
find . -type f -exec sed -i 's#\$name = \$_POST\['name']#\$name2 = \$_POST\['name']#g' {} \;
then it does not work - I don't get any errors thrown and the file system shows that the file has changed in that the modified date changes but the actual string is not replaced.
Is there a special consideration for strings containing spaces, $ or '? I have tried / and \ to no avail
I figured this out in the end - I used:
find . -type f -name '*.php' -exec sed -i -e "s#\$name = \$_POST\['name']#\$name2 = \$_POST\['name']#g" '{}' \;
The $ and [ needed to be escaped and changing to the # as the delimiter from , in my case made it work.
I always thought as long as the delimiter was not in your string to find or replace then anything could be used but then I read that # has some special meaning though I cannot find the SO article I read it on right now.
These SSH commands work in changing text for several files in a directory
replace "old-string" "new-String" -- *.ext
replace "old-string" "new-String" -- *
replace "old-string" "new-String" -- filename
however these won't target subdirectories... anybody knows the command to include ALL subdirectories?
I think sed is better for this. Your first two examples can be rewritten:
find . -type f | xargs sed -i s/old-string/new-string/g
find . -type f -name '*.ext' | xargs sed -i s/old-string/new-string/g
You can also pipe the results of find to your replace command, if that is better for you.
I want to insert a line into the start of multiple specified type files, which the files are located in current directory or the sub dir.
I know that using
find . -name "*.csv"
can help me to list the files I want to use for inserting.
and using
sed -i '1icolumn1,column2,column3' test.csv
can use to insert one line at the start of file,
but now I do NOT know how to pipe the filenames from "find" command to "sed" command.
Could anybody give me any suggestion?
Or is there any better solution to do this?
BTW, is it work to do this in one line command?
Try using xargs to pass output of find and command line arguments to next command, here sed
find . -type f -name '*.csv' -print0 | xargs -0 sed -i '1icolumn1,column2,column3'
Another option would be to use -exec option of find.
find . -type f -name '*.csv' -exec sed -i '1icolumn1,column2,column3' {} \;
Note : It has been observed that xargs is more efficient way and can handle multiple processes using -P option.
This way :
find . -type f -name "*.csv" -exec sed -i '1icolumn1,column2,column3' {} +
-exec do all the magic here. The relevant part of man find :
-exec command ;
Execute command; true if 0 status is returned. All following arguments
to find are taken to be arguments to the command until an argument consisting
of `;' is encountered. The string `{}' is replaced by the current file name
being processed everywhere it occurs in the arguments to the command, not just
in arguments where it is alone, as in some versions of find. Both of
these constructions might need to be escaped (with a `\') or quoted to protect
them from expansion by the shell. See the EXAMPLES section for examples of
the use of the -exec option. The specified command is run once for each
matched file. The command is executed in the starting directory. There
are unavoidable security problems surrounding use of the -exec action;
you should use the -execdir option instead
I need to replace some string into another in files. I know how to do that with single file: sed -i 's/a/b/'. But what about recursive function? I think I have to use find . -name * with xargs somehow.
I need your help :)
You are correct, find and xargs are what you want to use. Here's an example which will find all files with the ".ext" file extension in the current folder and all subfolders ,and replace the letter a with the letter b in the files.
find . -name "*.ext" | xargs sed -i 's/a/b/g'