1

I'm trying to setup a script that will fetch changes from github where a script has a command that's not executable in Mac OS X.
What I'm aiming for is to use sed etc to replace the command within that script.

These are the commands:

Original command (to be replaced in script):

DIR=$(dirname "$(readlink -f $0)")

New command (I want to replace with):

DIR="$(cd "$(dirname "$0")" && pwd -P)"

What I've tried so far:

StartStopScript="/path/to/script.sh"

DIRnew=""$(cd "$(dirname "$0")" && pwd -P)""

DIRold=""$(dirname "$(readlink -f $0)")""

echo "$StartStopScript" | sed -e 's/"$DIRold"/"$DIRnew"/g'

This fails and the commands seems to be executed instead of interpreted as a string.
Figure it comes down to quoting in sed.

Grateful for any help I can get with this.

4
  • should $OrigScript == $StartStopScript?
    – FelixJN
    Aug 14, 2015 at 11:00
  • I would strongly advice to use an if loop defining the OS in the script as in if [ OS = Mac ] ; then cmd=MacCommand ; else cmd=LinuxCommand ; fi. Replacing a string from a variable with sed's special characters like & in them is a mess, as you would have to escape them while defining the variable in the first place (e.g. DIRnew='"$(... \&\& pwd -P )"')
    – FelixJN
    Aug 14, 2015 at 11:14
  • @Fiximan:Correct OrigScript and StartstopScript should be the same. I've edit my post accordingly. No need to have an OS check since this script will only be run on Mac's, since the original script works out of the box on Linux. Aug 14, 2015 at 12:01
  • You are using "/" as separator in sed, but your content also contains some '/'. replace the sed with : sed -e "s,${DIRold},${DIRnew},g" Aug 10 at 14:54

1 Answer 1

0
OrigScript="/path/to/script.sh"
echo $OrigScript
/path/to/script.sh
#note: no quotes
OrigScript='"/path/to/script.sh"'
echo $OrigScript
"/path/to/script.sh"
#note: with quotes, but not good for filesnames, rather use "$filename" in the command argument


DIRnew='"$(cd "$(dirname "$0")" \&\& pwd -P)"'
echo $DIRnew
"$(cd "$(dirname "$0")" \&\& pwd -P)"
#note: with quotes, escaping & needed for suppressing interpretation by sed

DIRold='"$(dirname "$(readlink -f $0)")"'
echo $DIRold
"$(dirname "$(readlink -f $0)")"
#note: in your question the original DIR=.. did NOT have double quotes,
#I assume a typo

sed -e "s/$DIRold/$DIRnew/g" "$OrigScript"
#note: $OrigScript should NOT have the double quotes in it!
#note: I assume $OrigScript == $StartStopScript

#test:
echo $DIRold | sed "s/$DIRold/$DIRnew/"
"$(cd "$(dirname "$0")" && pwd -P)"
#result includes double quotes!

1) for declaring a variable with (double) quotes, you need to escape the quotes to have the quotes in the string, better use single quotes to make sure the string inside is exactly just the string and no variables are interpreted. This also simplifies the use of &, and $() as the are then not interpreted by the shell

2) for echoing (double) quotes, escape them

3) for allowing sed to interpret a shell variable, you MUST use double quotes around the sed command ( with single quotes, the command sed 's/$a/$b/' will try to replace the actual string '$a' with the string '$b' , also be aware of the special meaning of $ in sed), double quotes around the variable within the sed command is not needed, as sed is for treating strings with any character (with restrictions regarding the special command characters of sed).

4) echo "$StartStopScript" | sed -e 's/"$DIRold"/"$DIRnew"/g' will echo the variable $StartStopScript ( which I assume is simply the file name of the script ) and try to replace the variables in that string (i.e. the file name). For applying sed to a file, use sed 's/a/b/g' file (output written to stout), for overwriting the file, use -i (use with care, i.e. test for the right substitutions first)

5) & has a special meaning in sed, it reprints the initial (matching) pattern:

echo ABC | sed 's/A/&12/'
A12BC

You will have to escape it in the replacement pattern to suppress interpretation:

echo ABC | sed 's/A/\&12/'
&12BC

Thus the variable $DIRnew needs to have the escape backslashes in its string.

6) Apart from that, I would suggest to rather use an if loop identifying the OS and to adapt the commands accordingly. That way you only need one script for both OSes. I.e.

if [ OS = Mac ] ; then
    dir=MacDir
else
    dir=LinuxDir
fi
1
  • Thanks! Very helpful post and walkthrough of each section of the script. Needed to make some smaller adjustments to get it running under OS X (sed -i '.bak') since sed was trowing up errors (undefined label). Aug 14, 2015 at 18:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .