Bash converting path names for sed so they escape [duplicate]

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
3
down vote

favorite













This question already has an answer here:



  • How to ensure that string interpolated into `sed` substitution escapes all metachars

    1 answer



I'm having a problem with a script. It is meant to change a value in a file called %DIR% so that it becomes a path name. The problem is the slashes in the directory name upset sed, so I get weird errors. I need to convert the slashes in the path name into escaped slashes.



So /var/www would become /var/www



But I don't know how to do this.



Currently the script runs sed with this:



sed -i "s/%DIR%/$directory/g" "$config"









share|improve this question















marked as duplicate by Stéphane Chazelas bash
Users with the  bash badge can single-handedly close bash questions as duplicates and reopen them as needed.

StackExchange.ready(function()
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function()
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function()
$hover.showInfoMessage('',
messageElement: $msg.clone().show(),
transient: false,
position: my: 'bottom left', at: 'top center', offsetTop: -7 ,
dismissable: false,
relativeToBody: true
);
,
function()
StackExchange.helpers.removeMessages();

);
);
);
Oct 1 at 8:43


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.










  • 2




    Why not just change the sed delimiter?
    – Bratchley
    Feb 23 '16 at 17:12







  • 1




    @Bratchley, probably because any delimiter you choose could be present in a file name (you can't use the NUL character: sed complains with "unterminated 's' command").
    – Toby Speight
    Feb 23 '16 at 17:20










  • @TobySpeight there are many different delimiters you can pick from. I highly doubt an asterisk would be in the filename, though.
    – Bratchley
    Feb 24 '16 at 15:56










  • I doubt it too. But being able to handle those cases is helpful when you might be dealing with hostile inputs (I'll leave it as an exercise to decide whether Bash is the right tool in such circumstances...).
    – Toby Speight
    Feb 27 at 9:04










  • Using ctrl-A as a delimiter is quite safely uniq : delim=$(printf '01') ; sed -e "s$delimregexp$delimreplacement$delim" . It doesn't have to be different from everything sed SEES but from everything is at "regexp" and "replacement" ... which is usually printable characters and regexps
    – Olivier Dulac
    Oct 1 at 13:34















up vote
3
down vote

favorite













This question already has an answer here:



  • How to ensure that string interpolated into `sed` substitution escapes all metachars

    1 answer



I'm having a problem with a script. It is meant to change a value in a file called %DIR% so that it becomes a path name. The problem is the slashes in the directory name upset sed, so I get weird errors. I need to convert the slashes in the path name into escaped slashes.



So /var/www would become /var/www



But I don't know how to do this.



Currently the script runs sed with this:



sed -i "s/%DIR%/$directory/g" "$config"









share|improve this question















marked as duplicate by Stéphane Chazelas bash
Users with the  bash badge can single-handedly close bash questions as duplicates and reopen them as needed.

StackExchange.ready(function()
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function()
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function()
$hover.showInfoMessage('',
messageElement: $msg.clone().show(),
transient: false,
position: my: 'bottom left', at: 'top center', offsetTop: -7 ,
dismissable: false,
relativeToBody: true
);
,
function()
StackExchange.helpers.removeMessages();

);
);
);
Oct 1 at 8:43


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.










  • 2




    Why not just change the sed delimiter?
    – Bratchley
    Feb 23 '16 at 17:12







  • 1




    @Bratchley, probably because any delimiter you choose could be present in a file name (you can't use the NUL character: sed complains with "unterminated 's' command").
    – Toby Speight
    Feb 23 '16 at 17:20










  • @TobySpeight there are many different delimiters you can pick from. I highly doubt an asterisk would be in the filename, though.
    – Bratchley
    Feb 24 '16 at 15:56










  • I doubt it too. But being able to handle those cases is helpful when you might be dealing with hostile inputs (I'll leave it as an exercise to decide whether Bash is the right tool in such circumstances...).
    – Toby Speight
    Feb 27 at 9:04










  • Using ctrl-A as a delimiter is quite safely uniq : delim=$(printf '01') ; sed -e "s$delimregexp$delimreplacement$delim" . It doesn't have to be different from everything sed SEES but from everything is at "regexp" and "replacement" ... which is usually printable characters and regexps
    – Olivier Dulac
    Oct 1 at 13:34













up vote
3
down vote

favorite









up vote
3
down vote

favorite












This question already has an answer here:



  • How to ensure that string interpolated into `sed` substitution escapes all metachars

    1 answer



I'm having a problem with a script. It is meant to change a value in a file called %DIR% so that it becomes a path name. The problem is the slashes in the directory name upset sed, so I get weird errors. I need to convert the slashes in the path name into escaped slashes.



So /var/www would become /var/www



But I don't know how to do this.



Currently the script runs sed with this:



sed -i "s/%DIR%/$directory/g" "$config"









share|improve this question
















This question already has an answer here:



  • How to ensure that string interpolated into `sed` substitution escapes all metachars

    1 answer



I'm having a problem with a script. It is meant to change a value in a file called %DIR% so that it becomes a path name. The problem is the slashes in the directory name upset sed, so I get weird errors. I need to convert the slashes in the path name into escaped slashes.



So /var/www would become /var/www



But I don't know how to do this.



Currently the script runs sed with this:



sed -i "s/%DIR%/$directory/g" "$config"




This question already has an answer here:



  • How to ensure that string interpolated into `sed` substitution escapes all metachars

    1 answer







bash sed quoting string escape-characters






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 23 '16 at 23:26









Gilles

512k12010151547




512k12010151547










asked Feb 23 '16 at 17:08









John Tate

68411223




68411223




marked as duplicate by Stéphane Chazelas bash
Users with the  bash badge can single-handedly close bash questions as duplicates and reopen them as needed.

StackExchange.ready(function()
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function()
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function()
$hover.showInfoMessage('',
messageElement: $msg.clone().show(),
transient: false,
position: my: 'bottom left', at: 'top center', offsetTop: -7 ,
dismissable: false,
relativeToBody: true
);
,
function()
StackExchange.helpers.removeMessages();

);
);
);
Oct 1 at 8:43


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.






marked as duplicate by Stéphane Chazelas bash
Users with the  bash badge can single-handedly close bash questions as duplicates and reopen them as needed.

StackExchange.ready(function()
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function()
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function()
$hover.showInfoMessage('',
messageElement: $msg.clone().show(),
transient: false,
position: my: 'bottom left', at: 'top center', offsetTop: -7 ,
dismissable: false,
relativeToBody: true
);
,
function()
StackExchange.helpers.removeMessages();

);
);
);
Oct 1 at 8:43


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.









  • 2




    Why not just change the sed delimiter?
    – Bratchley
    Feb 23 '16 at 17:12







  • 1




    @Bratchley, probably because any delimiter you choose could be present in a file name (you can't use the NUL character: sed complains with "unterminated 's' command").
    – Toby Speight
    Feb 23 '16 at 17:20










  • @TobySpeight there are many different delimiters you can pick from. I highly doubt an asterisk would be in the filename, though.
    – Bratchley
    Feb 24 '16 at 15:56










  • I doubt it too. But being able to handle those cases is helpful when you might be dealing with hostile inputs (I'll leave it as an exercise to decide whether Bash is the right tool in such circumstances...).
    – Toby Speight
    Feb 27 at 9:04










  • Using ctrl-A as a delimiter is quite safely uniq : delim=$(printf '01') ; sed -e "s$delimregexp$delimreplacement$delim" . It doesn't have to be different from everything sed SEES but from everything is at "regexp" and "replacement" ... which is usually printable characters and regexps
    – Olivier Dulac
    Oct 1 at 13:34













  • 2




    Why not just change the sed delimiter?
    – Bratchley
    Feb 23 '16 at 17:12







  • 1




    @Bratchley, probably because any delimiter you choose could be present in a file name (you can't use the NUL character: sed complains with "unterminated 's' command").
    – Toby Speight
    Feb 23 '16 at 17:20










  • @TobySpeight there are many different delimiters you can pick from. I highly doubt an asterisk would be in the filename, though.
    – Bratchley
    Feb 24 '16 at 15:56










  • I doubt it too. But being able to handle those cases is helpful when you might be dealing with hostile inputs (I'll leave it as an exercise to decide whether Bash is the right tool in such circumstances...).
    – Toby Speight
    Feb 27 at 9:04










  • Using ctrl-A as a delimiter is quite safely uniq : delim=$(printf '01') ; sed -e "s$delimregexp$delimreplacement$delim" . It doesn't have to be different from everything sed SEES but from everything is at "regexp" and "replacement" ... which is usually printable characters and regexps
    – Olivier Dulac
    Oct 1 at 13:34








2




2




Why not just change the sed delimiter?
– Bratchley
Feb 23 '16 at 17:12





Why not just change the sed delimiter?
– Bratchley
Feb 23 '16 at 17:12





1




1




@Bratchley, probably because any delimiter you choose could be present in a file name (you can't use the NUL character: sed complains with "unterminated 's' command").
– Toby Speight
Feb 23 '16 at 17:20




@Bratchley, probably because any delimiter you choose could be present in a file name (you can't use the NUL character: sed complains with "unterminated 's' command").
– Toby Speight
Feb 23 '16 at 17:20












@TobySpeight there are many different delimiters you can pick from. I highly doubt an asterisk would be in the filename, though.
– Bratchley
Feb 24 '16 at 15:56




@TobySpeight there are many different delimiters you can pick from. I highly doubt an asterisk would be in the filename, though.
– Bratchley
Feb 24 '16 at 15:56












I doubt it too. But being able to handle those cases is helpful when you might be dealing with hostile inputs (I'll leave it as an exercise to decide whether Bash is the right tool in such circumstances...).
– Toby Speight
Feb 27 at 9:04




I doubt it too. But being able to handle those cases is helpful when you might be dealing with hostile inputs (I'll leave it as an exercise to decide whether Bash is the right tool in such circumstances...).
– Toby Speight
Feb 27 at 9:04












Using ctrl-A as a delimiter is quite safely uniq : delim=$(printf '01') ; sed -e "s$delimregexp$delimreplacement$delim" . It doesn't have to be different from everything sed SEES but from everything is at "regexp" and "replacement" ... which is usually printable characters and regexps
– Olivier Dulac
Oct 1 at 13:34





Using ctrl-A as a delimiter is quite safely uniq : delim=$(printf '01') ; sed -e "s$delimregexp$delimreplacement$delim" . It doesn't have to be different from everything sed SEES but from everything is at "regexp" and "replacement" ... which is usually printable characters and regexps
– Olivier Dulac
Oct 1 at 13:34











4 Answers
4






active

oldest

votes

















up vote
10
down vote



accepted










Since you say you are using Bash, you can use Parameter Expansion to insert the slashes:



$ directory=/var/www
$ echo "$directory////\/"
/var/www


This breaks up as



  • substitute directory

  • replacing every (//)

  • slash (/)

  • with (/)

  • backslash+slash (\/).

Putting this into your sed command gives:



sed -i "s/%DIR%/$directory////\//g" "$config"





share|improve this answer





























    up vote
    3
    down vote













    Use parameter expansion / substitution:



    $directory////\/


    Explanation



    $directory // / / \/
    ^ ^ ^ ^
    | | | |
    | | | replacement, backslash needs to be backslashed
    | | delimiter
    | string
    global
    substitution





    share|improve this answer





























      up vote
      2
      down vote













      You can use bash's string manipulation facilities provided by parameter expansion, specifically the $VARIABLE//PATTERN/REPLACEMENT form. Keep in mind that / isn't the only character that needs replacing: in an s replacement, the characters , &, newline, and the s separator all need to be prefixed with a backslash.



      replacement=$directory
      replacement=$replacement//\/\\
      replacement=$replacement////\/
      replacement=$replacement//&/\&
      replacement=$replacement//$'n'/\$'n'
      sed -i "s/%DIR%/$replacement/g" -- "$config"


      Alternatively, use a tool that doesn't require such quoting, such as awk or Perl.



      directory=$directory awk 'gsub(/%DIR%/, ENVIRON["directory"]) 1' <"$config" >"$config.new" &&
      mv -- "$config.new" "$config"


      or



      directory=$directory perl -i -pe 's/%DIR%/$ENVdirectory/g' "$config"





      share|improve this answer



























        up vote
        1
        down vote













        The other answers here are already great, but I just wanted to add that you can use a different delimiter besides / with sed. I do this whenever I need to operate on input that contains /:



        sed -i "s@%DIR%@$directory@g" "$config"


        Or even:



        sed -i "s#%DIR%#$directory#g" "$config"


        It's all the same to sed; it will use whatever character you specify after the s as the delimiter.






        share|improve this answer



























          4 Answers
          4






          active

          oldest

          votes








          4 Answers
          4






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          10
          down vote



          accepted










          Since you say you are using Bash, you can use Parameter Expansion to insert the slashes:



          $ directory=/var/www
          $ echo "$directory////\/"
          /var/www


          This breaks up as



          • substitute directory

          • replacing every (//)

          • slash (/)

          • with (/)

          • backslash+slash (\/).

          Putting this into your sed command gives:



          sed -i "s/%DIR%/$directory////\//g" "$config"





          share|improve this answer


























            up vote
            10
            down vote



            accepted










            Since you say you are using Bash, you can use Parameter Expansion to insert the slashes:



            $ directory=/var/www
            $ echo "$directory////\/"
            /var/www


            This breaks up as



            • substitute directory

            • replacing every (//)

            • slash (/)

            • with (/)

            • backslash+slash (\/).

            Putting this into your sed command gives:



            sed -i "s/%DIR%/$directory////\//g" "$config"





            share|improve this answer
























              up vote
              10
              down vote



              accepted







              up vote
              10
              down vote



              accepted






              Since you say you are using Bash, you can use Parameter Expansion to insert the slashes:



              $ directory=/var/www
              $ echo "$directory////\/"
              /var/www


              This breaks up as



              • substitute directory

              • replacing every (//)

              • slash (/)

              • with (/)

              • backslash+slash (\/).

              Putting this into your sed command gives:



              sed -i "s/%DIR%/$directory////\//g" "$config"





              share|improve this answer














              Since you say you are using Bash, you can use Parameter Expansion to insert the slashes:



              $ directory=/var/www
              $ echo "$directory////\/"
              /var/www


              This breaks up as



              • substitute directory

              • replacing every (//)

              • slash (/)

              • with (/)

              • backslash+slash (\/).

              Putting this into your sed command gives:



              sed -i "s/%DIR%/$directory////\//g" "$config"






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Oct 1 at 7:49

























              answered Feb 23 '16 at 17:14









              Toby Speight

              5,1211930




              5,1211930






















                  up vote
                  3
                  down vote













                  Use parameter expansion / substitution:



                  $directory////\/


                  Explanation



                  $directory // / / \/
                  ^ ^ ^ ^
                  | | | |
                  | | | replacement, backslash needs to be backslashed
                  | | delimiter
                  | string
                  global
                  substitution





                  share|improve this answer


























                    up vote
                    3
                    down vote













                    Use parameter expansion / substitution:



                    $directory////\/


                    Explanation



                    $directory // / / \/
                    ^ ^ ^ ^
                    | | | |
                    | | | replacement, backslash needs to be backslashed
                    | | delimiter
                    | string
                    global
                    substitution





                    share|improve this answer
























                      up vote
                      3
                      down vote










                      up vote
                      3
                      down vote









                      Use parameter expansion / substitution:



                      $directory////\/


                      Explanation



                      $directory // / / \/
                      ^ ^ ^ ^
                      | | | |
                      | | | replacement, backslash needs to be backslashed
                      | | delimiter
                      | string
                      global
                      substitution





                      share|improve this answer














                      Use parameter expansion / substitution:



                      $directory////\/


                      Explanation



                      $directory // / / \/
                      ^ ^ ^ ^
                      | | | |
                      | | | replacement, backslash needs to be backslashed
                      | | delimiter
                      | string
                      global
                      substitution






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Feb 23 '16 at 17:25

























                      answered Feb 23 '16 at 17:12









                      choroba

                      25k34168




                      25k34168




















                          up vote
                          2
                          down vote













                          You can use bash's string manipulation facilities provided by parameter expansion, specifically the $VARIABLE//PATTERN/REPLACEMENT form. Keep in mind that / isn't the only character that needs replacing: in an s replacement, the characters , &, newline, and the s separator all need to be prefixed with a backslash.



                          replacement=$directory
                          replacement=$replacement//\/\\
                          replacement=$replacement////\/
                          replacement=$replacement//&/\&
                          replacement=$replacement//$'n'/\$'n'
                          sed -i "s/%DIR%/$replacement/g" -- "$config"


                          Alternatively, use a tool that doesn't require such quoting, such as awk or Perl.



                          directory=$directory awk 'gsub(/%DIR%/, ENVIRON["directory"]) 1' <"$config" >"$config.new" &&
                          mv -- "$config.new" "$config"


                          or



                          directory=$directory perl -i -pe 's/%DIR%/$ENVdirectory/g' "$config"





                          share|improve this answer
























                            up vote
                            2
                            down vote













                            You can use bash's string manipulation facilities provided by parameter expansion, specifically the $VARIABLE//PATTERN/REPLACEMENT form. Keep in mind that / isn't the only character that needs replacing: in an s replacement, the characters , &, newline, and the s separator all need to be prefixed with a backslash.



                            replacement=$directory
                            replacement=$replacement//\/\\
                            replacement=$replacement////\/
                            replacement=$replacement//&/\&
                            replacement=$replacement//$'n'/\$'n'
                            sed -i "s/%DIR%/$replacement/g" -- "$config"


                            Alternatively, use a tool that doesn't require such quoting, such as awk or Perl.



                            directory=$directory awk 'gsub(/%DIR%/, ENVIRON["directory"]) 1' <"$config" >"$config.new" &&
                            mv -- "$config.new" "$config"


                            or



                            directory=$directory perl -i -pe 's/%DIR%/$ENVdirectory/g' "$config"





                            share|improve this answer






















                              up vote
                              2
                              down vote










                              up vote
                              2
                              down vote









                              You can use bash's string manipulation facilities provided by parameter expansion, specifically the $VARIABLE//PATTERN/REPLACEMENT form. Keep in mind that / isn't the only character that needs replacing: in an s replacement, the characters , &, newline, and the s separator all need to be prefixed with a backslash.



                              replacement=$directory
                              replacement=$replacement//\/\\
                              replacement=$replacement////\/
                              replacement=$replacement//&/\&
                              replacement=$replacement//$'n'/\$'n'
                              sed -i "s/%DIR%/$replacement/g" -- "$config"


                              Alternatively, use a tool that doesn't require such quoting, such as awk or Perl.



                              directory=$directory awk 'gsub(/%DIR%/, ENVIRON["directory"]) 1' <"$config" >"$config.new" &&
                              mv -- "$config.new" "$config"


                              or



                              directory=$directory perl -i -pe 's/%DIR%/$ENVdirectory/g' "$config"





                              share|improve this answer












                              You can use bash's string manipulation facilities provided by parameter expansion, specifically the $VARIABLE//PATTERN/REPLACEMENT form. Keep in mind that / isn't the only character that needs replacing: in an s replacement, the characters , &, newline, and the s separator all need to be prefixed with a backslash.



                              replacement=$directory
                              replacement=$replacement//\/\\
                              replacement=$replacement////\/
                              replacement=$replacement//&/\&
                              replacement=$replacement//$'n'/\$'n'
                              sed -i "s/%DIR%/$replacement/g" -- "$config"


                              Alternatively, use a tool that doesn't require such quoting, such as awk or Perl.



                              directory=$directory awk 'gsub(/%DIR%/, ENVIRON["directory"]) 1' <"$config" >"$config.new" &&
                              mv -- "$config.new" "$config"


                              or



                              directory=$directory perl -i -pe 's/%DIR%/$ENVdirectory/g' "$config"






                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Feb 24 '16 at 1:06









                              Gilles

                              512k12010151547




                              512k12010151547




















                                  up vote
                                  1
                                  down vote













                                  The other answers here are already great, but I just wanted to add that you can use a different delimiter besides / with sed. I do this whenever I need to operate on input that contains /:



                                  sed -i "s@%DIR%@$directory@g" "$config"


                                  Or even:



                                  sed -i "s#%DIR%#$directory#g" "$config"


                                  It's all the same to sed; it will use whatever character you specify after the s as the delimiter.






                                  share|improve this answer
























                                    up vote
                                    1
                                    down vote













                                    The other answers here are already great, but I just wanted to add that you can use a different delimiter besides / with sed. I do this whenever I need to operate on input that contains /:



                                    sed -i "s@%DIR%@$directory@g" "$config"


                                    Or even:



                                    sed -i "s#%DIR%#$directory#g" "$config"


                                    It's all the same to sed; it will use whatever character you specify after the s as the delimiter.






                                    share|improve this answer






















                                      up vote
                                      1
                                      down vote










                                      up vote
                                      1
                                      down vote









                                      The other answers here are already great, but I just wanted to add that you can use a different delimiter besides / with sed. I do this whenever I need to operate on input that contains /:



                                      sed -i "s@%DIR%@$directory@g" "$config"


                                      Or even:



                                      sed -i "s#%DIR%#$directory#g" "$config"


                                      It's all the same to sed; it will use whatever character you specify after the s as the delimiter.






                                      share|improve this answer












                                      The other answers here are already great, but I just wanted to add that you can use a different delimiter besides / with sed. I do this whenever I need to operate on input that contains /:



                                      sed -i "s@%DIR%@$directory@g" "$config"


                                      Or even:



                                      sed -i "s#%DIR%#$directory#g" "$config"


                                      It's all the same to sed; it will use whatever character you specify after the s as the delimiter.







                                      share|improve this answer












                                      share|improve this answer



                                      share|improve this answer










                                      answered Feb 24 '16 at 21:19









                                      Will

                                      1,451722




                                      1,451722












                                          Popular posts from this blog

                                          How to check contact read email or not when send email to Individual?

                                          Displaying single band from multi-band raster using QGIS

                                          How many registers does an x86_64 CPU actually have?