-1

I am trying to replace a script call with a script call from a sub directory.

For example, originally I had ./output.sh in my script to call the output.sh script in the current directory.

I want to replace ./output.sh with ../output.sh so that it calls output.sh in the parent directory.

I tried

sed -i -e 's/../\output.sh/./\output.sh/g' scriptName.sh

This returns with

char 17: unknown option to 's'

Any help with the sed escape character syntax would be great.

Inian
  • 80,270
  • 14
  • 142
  • 161
NickaBrick
  • 81
  • 1
  • 12
  • 1
    To replace "./output.sh" with "../output.sh", you can try `sed 's@\([^.]\)\./output\.sh@\1../output.sh@g` (this won't match entries at the beginning of the line, but gives you a good start on a solution). But this is not the correct way to solve your problem! – William Pursell Jan 05 '17 at 17:35
  • Or [sed search and replace strings containing /](http://stackoverflow.com/q/10309968/3266847) or [Use slashes in sed replace](http://stackoverflow.com/q/5864146/3266847) – Benjamin W. Jan 05 '17 at 18:07

3 Answers3

1

Sed is bad at this; you'll risk turning an already existing ../output.sh into .../output.sh if you're not careful.

This is the best sed can do:

sed -i 's@output\.sh@../$@g' scriptName.sh

(I'm using @ in place of / so that there are no forward slashes to escape. Sed accepts any punctuation character in place of forward slash.)

Note that this will convert ../output.sh to ../../output.sh but at least it doesn't create that triple-dot error.

Instead, try perl:

perl -pie 's@(?<!\.\./)(output\.sh\b)@../$1@g' scriptName.sh

This uses a negative look-behind to ensure it doesn't traverse to the parent's parent. It also allows using \b to denote a word break just in case you have something like output.shelf somewhere.

Adam Katz
  • 14,455
  • 5
  • 68
  • 83
0

The slash character is special in sed's s command if you formulate it as s/something/replacement/flags, so the slashes in your file paths cause the error. Fortunately, you can use any other character right after s, for example s@something@replacement@flags. So, replacing the command with s@\./output.sh@../output.sh@g should do the trick.

Note two additional changes: you have to escape the dot in first expression since it's also a special character in regex and you also got reversed order of search expression and replacement (thanks charli for noticing this). You don't need the backslashes before o characters, either.

Alternatively, you can use / after s but escape the literal slashes you want to replace by preceding them with backslashes: s/\.\/output.sh/..\/\output.sh/g. It seems in your code you tried to use this solution but put the backslashes after instead of before the slashes.

Michał Kosmulski
  • 9,855
  • 1
  • 32
  • 51
  • 1
    If you don't escape the dots, it can replace strings as `directory/output.sh` to `director./output.sh`. Also, the question is to change from `./output.sh` to `../output.sh`, your patterns are reversed. – charli Jan 05 '17 at 17:47
  • 1
    @charli Thanks for pointing this out. There were so many issues with the original expression I just skimmed over them without noticing. – Michał Kosmulski Jan 06 '17 at 08:46
0

This would do the trick. Substitutes every appearance of ./output.sh for ../output.sh :

sed 's/\.\/output\.sh/\.\.\/output\.sh/g' scriptName.sh

The escape character is \. You should use it to escape:

  • Every dot .. The dot is used as any character in regex.
  • Every slash /. The slash character is used as delimiter between regex on the scommand.
charli
  • 1,700
  • 1
  • 13
  • 21