sed command not working in mac - bash

Following sed command is not working on my lion mac.
find . -type f -exec sed -i 's/user_dashboard/user/g' {} \;
I am getting this error
sed: 1: "./vendor/assets/javascr ...": invalid command code .

The OSX version of sed is not the same as those found in most Linux systems.
It extends the -i option to give you the opportunity save a file with a different extension, but requires input for that extension.
If you just want to overwrite the file in place, you need to use sed -i "" ...sedCmd.... fileName to rename your file in-place.
Per #JamesMcMahon 's comment, see here for the full doc for OSX/BSD sed.
I hope this helps.

-i probably has a different meaning (not "in-place") in your version of sed. Try using gsed if available or replacing -i with -e and using a temporary file (and a mv afterwards) to emulate it.

replacing text inside a file on the fly with sed on mac is possible,
the command is just a little different.
with: -i , you have to specify a postfix, which sed will use to save the original file after it modified it.
run the command as:
$ sed -i _backup -E 's/foo/bar/' /tmp/jestinkt.txt
ending with both the modified /tmp/jestinkt.txt and the original /tmp/jestinkt.txt_backup

Related

Sed delete first line from files

I want to remove the first line of all files in a folder if the file starts with uuid and so I have a working sed command looking like this:
$ sed -i '' '/^uuid/d' *
which works fine and removes all lines starting with uuid.
Now I want to improve the script by only removing the first line if it starts with uuid since some of the files has multiple uuid:s and only the one on the first line should be deleted. So now I improved the command to look like this:
$ sed -i '' '1{/^uuid/d;}' *
Now this command also works but only on the first file in the folder and even if I run a simple (just remove first line) version like:
$ sed -i '' '1d' *
it still only affects the first file.
Why is this?
I'm on Mac (so the BSD version of sed as I've come to understand) and I also tried installing the gnu-sed version via Brew, $ brew install gnu-sed --with-default-names, with no luck.
I've read sed - 25 examples to delete a line or pattern in a file,
sed - 20 examples to remove / delete characters from a file and googled sed delete first line in files
UPDATE 1: As proposed in the comments by john1024 I've tested with the -s option but not sure how to use it.
$ sed -s '1d' ./*
sed: illegal option -- s
When I check man sed I can find the -s & --seperateoption so I must do something wrong here.
UPDATE 2: Ok, progress ... find . -iname '*.yml' -exec sed -i '' -e '1{/uuid/d;}' {} \; does the trick but I get error message saying sed: can't read : No such file or directory
Thanks for any help or guidance!
:ola
sed -i '' '1{/^uuid/d;}' * will modify only the first file,
because the line numbers are counted cumulatively across files,
so "line 1" occurs only once, it's the first line of the first file.
To do something with the first line of multiple files,
you need to run sed once per file.
You can do that using a simple for loop:
for f in *; do sed -i '' '1{/^uuid/d;}' "$f"; done

Iterating through files in a folder with sed

I've a list of csv-files and would like to use a for loop to edit the content for each file. I'd like to do that with sed. I have this sed commands which works fine when testing it on one file:
sed 's/[ "-]//g'
So now I want to execute this command for each file in a folder. I've tried this but so far no luck:
for i in *.csv; do sed 's/[ "-]//g' > $i.csv; done
I would like that he would overwrite each file with the edit performed by sed. The sed commands removes all spaces, the " and the '-' character.
Small changes,
for i in *.csv
do
sed -i 's/[ "-]//g' "$i"
done
Changes
when you iterate through the for you get the filenames in $i as example one.csv, two.csv etc. You can directly use these as input to the sed command.
-i Is for inline changes, the sed will do the substitution and updates the file for you. No output redirection is required.
In the code you wrote, I guess you missed any inputs to the sed command
In my case i want to replace every first occurrence of a particular string in each line for several text files, i've use the following:
//want to replace 16 with 1 in each files only for the first occurance
sed -i 's/16/1/' *.txt
In your case, In terminal you can try this
sed 's/[ "-]//g' *.csv
In certain scenarios it might be worth considering finding the files and executing a command on them like explained in this answer (as stated there, make sure echo $PATH doesn't contain .)
find /path/to/csv/ -type f '*.csv' -execdir sed -i 's/[ "-]//g' {} \;
here we:
find all files (type f) which end with .csv in the folder /path/to/csv/
sed the found files in place, ie we replace the original files with the changed version instead of creating numbered csv files ($i.csv)

How can I avoid creation of the extra file with `-e` while using the sed tool in a shell script?

I am using sed command in a shell script to edit & replace some file content of an xml file in a osx(unix) environment. Is there some way I can avoid sed creating the temporary files with -e ? I am doing the following in my script to edit a file with sed.
sed -i -e 's/abc/xyz/g' /PathTo/MyEditableFile.xml
Above sed command works great but creates an extra file as /PathTo/MyEditableFile.xml-e
How can I avoid creation of the the extra file with -e there ?
I tried some options like setting a temporary folder path to sed so that it creates the temporary file in /tmp/. Like so:
sed -i -e 's/abc/xyz/g' /PathTo/MyEditableFile.xml >/tmp
But doesnt seem to work
As you are editing the file in place (-i), OS X sed requires a mandatory backup filename.
You can use -i "" to get around this:
sed -i "" -e 's/abc/xyz/g' /PathTo/MyEditableFile.xml

replace a string in file using shell script

Suppose my file a.conf is as following
Include /1
Include /2
Include /3
I want to replace "Include /2" with a new line, I write the code in .sh file :
line="Include /2"
rep=""
sed -e "s/${line}/${rep}/g" /root/new_scripts/a.conf
But after running the sh file, It give me the following error
sed: -e expression #1, char 14: unknown option to `s'
If you are using a newer version of sed you can use -i to read from and write to the same file. Using -i you can specify a file extension so a backup will be made, incase something went wrong. Also you don't need to use the -e flag unless you are using multiple commands
sed -i.bak "s/${line}/${rep}/g" /root/new_scripts/a.conf
I have just noticed that as the variables you are using are quoted strings you may want to use single quotes around your sed expression. Also your string contains a forward slash, to avoid any errors you can use a different delimiter in your sed command (the delimiter doesn't need to be a slash):
sed -i.bak 's|${line}|${rep}|g' /root/new_scripts/a.conf
You have to write the changes to a new file and then, move the new file over the old one. Like this:
line="Include 2"
rep=""
sed -e "s/${line}/${rep}/g" /root/new_scripts/a.conf > /root/new_scripts/a.conf-new
mv /root/new_scripts/a.conf-new /root/new_scripts/a.conf
The redirection (> /root/new_scripts/a.conf) wipes the contents of the file before sed can see it.
You need to pass the -i option to sed to edit the file in-place:
sed -i "s/${line}/${rep}/g" /root/new_scripts/a.conf
You can also ask sed to create a backup of the original file:
sed -i.bak "s/${line}/${rep}/g" /root/new_scripts/a.conf
So, if you have to replace a substring in a file, you can use sed command like this, say we have a file as file.txt, so replacing a substring in it can be done like this
searchString="abc";
replaceString="def";
sed -i '' "s|$searchString|$replaceString|g" file.txt
This will all the occurrences of "abc" with "def" in file.txt. Also, this keeps a check for any / character present in the variables used, and with no backup file made.

In-place edits with sed on OS X

I'd like edit a file with sed on OS X. I'm using the following command:
sed 's/oldword/newword/' file.txt
The output is sent to the terminal. file.txt is not modified. The changes are saved to file2.txt with this command:
sed 's/oldword/newword/' file1.txt > file2.txt
However I don't want another file. I just want to edit file1.txt. How can I do this?
I've tried the -i flag. This results in the following error:
sed: 1: "file1.txt": invalid command code f
You can use the -i flag correctly by providing it with a suffix to add to the backed-up file. Extending your example:
sed -i.bu 's/oldword/newword/' file1.txt
Will give you two files: one with the name file1.txt that contains the substitution, and one with the name file1.txt.bu that has the original content.
Mildly dangerous
If you want to destructively overwrite the original file, use something like:
sed -i '' 's/oldword/newword/' file1.txt
^ note the space
Because of the way the line gets parsed, a space is required between the option flag and its argument because the argument is zero-length.
Other than possibly trashing your original, I’m not aware of any further dangers of tricking sed this way. It should be noted, however, that if this invocation of sed is part of a script, The Unix Way™ would (IMHO) be to use sed non-destructively, test that it exited cleanly, and only then remove the extraneous file.
I've similar problem with MacOS
sed -i '' 's/oldword/newword/' file1.txt
doesn't works, but
sed -i"any_symbol" 's/oldword/newword/' file1.txt
works well.
The -i flag probably doesn't work for you, because you followed an example for GNU sed while macOS uses BSD sed and they have a slightly different syntax.
All the other answers tell you how to correct the syntax to work with BSD sed. The alternative is to install GNU sed on your macOS with:
brew install gsed
and then use it instead of the sed version shipped with macOS (note the g prefix), e.g:
gsed -i 's/oldword/newword/' file1.txt
If you want GNU sed commands to be always portable to your macOS, you could prepend "gnubin" directory to your path, by adding something like this to your .bashrc/.zshrc file (run brew info gsed to see what exactly you need to do):
export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
and from then on the GNU sed becomes your default sed and you can simply run:
sed -i 's/oldword/newword/' file1.txt
sed -i -- "s/https/http/g" file.txt
You can use -i'' (--in-place) for sed as already suggested. See: The -i in-place argument, however note that -i option is non-standard FreeBSD extensions and may not be available on other operating systems. Secondly sed is a Stream EDitor, not a file editor.
Alternative way is to use built-in substitution in Vim Ex mode, like:
$ ex +%s/foo/bar/g -scwq file.txt
and for multiple-files:
$ ex +'bufdo!%s/foo/bar/g' -scxa *.*
To edit all files recursively you can use **/*.* if shell supports that (enable by shopt -s globstar).
Another way is to use gawk and its new "inplace" extension such as:
$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1
This creates backup files. E.g. sed -i -e 's/hello/hello world/' testfile for me, creates a backup file, testfile-e, in the same dir.
You can use:
sed -i -e 's/<string-to-find>/<string-to-replace>/' <your-file-path>
Example:
sed -i -e 's/Hello/Bye/' file.txt
This works flawless in Mac.
If you need to substitute more than one different words:
sed -i '' -e 's/_tools/tools/' -e 's/_static/static/' test.txt

Resources