Dealing with space in file links using bash












1














I got a problem. Here is my bash script to merge videos with subs:



#!/bin/bash 

cd /media/ptrknvk/'TOSHIBA EXT'/Shows/My/'Doctor Who'/

url0='DW s11e0'
url1='DW s11e'

for(( i=1; i<11; i++ ))
do
if ! [ $i -gt 9 ];
then
mkvmerge -o $url0$i.mkv $url0$i.mkv $url0$i.srt
rm $url0$i.srt
else
mkvmerge -o $url1$i.mkv $url1$i.mkv $url1$i.srt
rm $url1$i.srt
fi
done


File have names like for example "DW s11e05.mkv" and they actually exist in the directory.



And here is a result:



mkvmerge v8.8.0 ('Wind at my back') 64bit
Error: The file 's11e09.mkv' could not be opened for reading: open file error.
rm: cannot remove 'DW': No such file or directory
rm: cannot remove 's11e09.srt': No such file or directory
mkvmerge v8.8.0 ('Wind at my back') 64bit
Error: The file 's11e10.mkv' could not be opened for reading: open file error.
rm: cannot remove 'DW': No such file or directory
rm: cannot remove 's11e10.srt': No such file or directory


As you can see '' before a space doesn't work here. I also tried to use echo, but nothing changed (mb I've used it in a wrong way).



Sorry for my little bit nooby style.










share|improve this question



























    1














    I got a problem. Here is my bash script to merge videos with subs:



    #!/bin/bash 

    cd /media/ptrknvk/'TOSHIBA EXT'/Shows/My/'Doctor Who'/

    url0='DW s11e0'
    url1='DW s11e'

    for(( i=1; i<11; i++ ))
    do
    if ! [ $i -gt 9 ];
    then
    mkvmerge -o $url0$i.mkv $url0$i.mkv $url0$i.srt
    rm $url0$i.srt
    else
    mkvmerge -o $url1$i.mkv $url1$i.mkv $url1$i.srt
    rm $url1$i.srt
    fi
    done


    File have names like for example "DW s11e05.mkv" and they actually exist in the directory.



    And here is a result:



    mkvmerge v8.8.0 ('Wind at my back') 64bit
    Error: The file 's11e09.mkv' could not be opened for reading: open file error.
    rm: cannot remove 'DW': No such file or directory
    rm: cannot remove 's11e09.srt': No such file or directory
    mkvmerge v8.8.0 ('Wind at my back') 64bit
    Error: The file 's11e10.mkv' could not be opened for reading: open file error.
    rm: cannot remove 'DW': No such file or directory
    rm: cannot remove 's11e10.srt': No such file or directory


    As you can see '' before a space doesn't work here. I also tried to use echo, but nothing changed (mb I've used it in a wrong way).



    Sorry for my little bit nooby style.










    share|improve this question

























      1












      1








      1







      I got a problem. Here is my bash script to merge videos with subs:



      #!/bin/bash 

      cd /media/ptrknvk/'TOSHIBA EXT'/Shows/My/'Doctor Who'/

      url0='DW s11e0'
      url1='DW s11e'

      for(( i=1; i<11; i++ ))
      do
      if ! [ $i -gt 9 ];
      then
      mkvmerge -o $url0$i.mkv $url0$i.mkv $url0$i.srt
      rm $url0$i.srt
      else
      mkvmerge -o $url1$i.mkv $url1$i.mkv $url1$i.srt
      rm $url1$i.srt
      fi
      done


      File have names like for example "DW s11e05.mkv" and they actually exist in the directory.



      And here is a result:



      mkvmerge v8.8.0 ('Wind at my back') 64bit
      Error: The file 's11e09.mkv' could not be opened for reading: open file error.
      rm: cannot remove 'DW': No such file or directory
      rm: cannot remove 's11e09.srt': No such file or directory
      mkvmerge v8.8.0 ('Wind at my back') 64bit
      Error: The file 's11e10.mkv' could not be opened for reading: open file error.
      rm: cannot remove 'DW': No such file or directory
      rm: cannot remove 's11e10.srt': No such file or directory


      As you can see '' before a space doesn't work here. I also tried to use echo, but nothing changed (mb I've used it in a wrong way).



      Sorry for my little bit nooby style.










      share|improve this question













      I got a problem. Here is my bash script to merge videos with subs:



      #!/bin/bash 

      cd /media/ptrknvk/'TOSHIBA EXT'/Shows/My/'Doctor Who'/

      url0='DW s11e0'
      url1='DW s11e'

      for(( i=1; i<11; i++ ))
      do
      if ! [ $i -gt 9 ];
      then
      mkvmerge -o $url0$i.mkv $url0$i.mkv $url0$i.srt
      rm $url0$i.srt
      else
      mkvmerge -o $url1$i.mkv $url1$i.mkv $url1$i.srt
      rm $url1$i.srt
      fi
      done


      File have names like for example "DW s11e05.mkv" and they actually exist in the directory.



      And here is a result:



      mkvmerge v8.8.0 ('Wind at my back') 64bit
      Error: The file 's11e09.mkv' could not be opened for reading: open file error.
      rm: cannot remove 'DW': No such file or directory
      rm: cannot remove 's11e09.srt': No such file or directory
      mkvmerge v8.8.0 ('Wind at my back') 64bit
      Error: The file 's11e10.mkv' could not be opened for reading: open file error.
      rm: cannot remove 'DW': No such file or directory
      rm: cannot remove 's11e10.srt': No such file or directory


      As you can see '' before a space doesn't work here. I also tried to use echo, but nothing changed (mb I've used it in a wrong way).



      Sorry for my little bit nooby style.







      bash scripts






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 1 hour ago









      Patrik Novák

      157




      157






















          2 Answers
          2






          active

          oldest

          votes


















          2














          You need to quote your variables. This should do what you want:



          #!/bin/bash 

          cd /media/ptrknvk/'TOSHIBA EXT'/Shows/My/'Doctor Who'/

          url0='DW s11e0'
          url1='DW s11e'

          for(( i=1; i<11; i++ ))
          do
          if ! [ $i -gt 9 ];
          then
          mkvmerge -o "$url0$i.mkv" "$url0$i.mkv" "$url0$i.srt" &&
          rm "$url0$i.srt"
          else
          mkvmerge -o "$url1$i.mkv" "$url1$i.mkv" "$url1$i.srt" &&
          rm "$url1$i.srt"
          fi
          done


          Note that I also added a && after each mkvmerge command so the rm only runs if the mkvmerge was successful. You don't want to delete the subtitle file if the merge failed!



          That said, although there's absolutely nothing wrong with your approach, I feel you could make it considerable simpler and more elegant using shell globbing instead:



          #!/bin/bash 

          for file in "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/"DW*mkv; do
          srtFile=${file//.mkv/.srt}
          mkvmerge -o "$file" "$file" "$srtFile" && rm "$srtFile"
          done


          You don't even need a script for this. You can just run it directly in the terminal as a one liner:



          for file in "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/"DW*mkv; do
          mkvmerge -o "$file" "$file" "${file//.mkv/.srt}" && rm "${file//.mkv/.srt}";
          done





          share|improve this answer































            3














            Quote variables to prevent word-splitting. By the way, double-quotes on a whole string is the preferred style.



            #!/bin/bash

            # Also exit if this fails
            cd "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/" || exit

            url0="DW s11e0"
            url1="DW s11e"

            for (( i=1; i<11; i++ )); do
            # Also why use "not greater-than" when "less-than-or-equal" exists?
            if [ $i -le 9 ]; then
            # Also you can DRY* out this part with variables.
            url="$url0"
            else
            url="$url1"
            fi
            # Also when concatenating variables, it's clearer to use the "${var}" style. **
            f_mkv="${url}${i}.mkv"
            f_srt="${url}${i}.srt"
            mkvmerge -o "$f_mkv" "$f_mkv" "$f_srt"
            rm "$f_srt"
            done


            Shellcheck is really useful for finding problems like this in shell scripts.



            * DRY = Don't Repeat Yourself



            ** Or you could use printf -v, but it's not a big improvement in this case. For example



            printf -v f_mkv "%s%s.mkv" "$url" $i





            share|improve this answer



















            • 2




              You may also wanna mention that using ${varname} style is better in cases where you are concatenating string with variable, so that the shell clearly knows what part of the token is a variable
              – Sergiy Kolodyazhnyy
              1 hour ago











            Your Answer








            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "89"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f1106116%2fdealing-with-space-in-file-links-using-bash%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            2














            You need to quote your variables. This should do what you want:



            #!/bin/bash 

            cd /media/ptrknvk/'TOSHIBA EXT'/Shows/My/'Doctor Who'/

            url0='DW s11e0'
            url1='DW s11e'

            for(( i=1; i<11; i++ ))
            do
            if ! [ $i -gt 9 ];
            then
            mkvmerge -o "$url0$i.mkv" "$url0$i.mkv" "$url0$i.srt" &&
            rm "$url0$i.srt"
            else
            mkvmerge -o "$url1$i.mkv" "$url1$i.mkv" "$url1$i.srt" &&
            rm "$url1$i.srt"
            fi
            done


            Note that I also added a && after each mkvmerge command so the rm only runs if the mkvmerge was successful. You don't want to delete the subtitle file if the merge failed!



            That said, although there's absolutely nothing wrong with your approach, I feel you could make it considerable simpler and more elegant using shell globbing instead:



            #!/bin/bash 

            for file in "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/"DW*mkv; do
            srtFile=${file//.mkv/.srt}
            mkvmerge -o "$file" "$file" "$srtFile" && rm "$srtFile"
            done


            You don't even need a script for this. You can just run it directly in the terminal as a one liner:



            for file in "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/"DW*mkv; do
            mkvmerge -o "$file" "$file" "${file//.mkv/.srt}" && rm "${file//.mkv/.srt}";
            done





            share|improve this answer




























              2














              You need to quote your variables. This should do what you want:



              #!/bin/bash 

              cd /media/ptrknvk/'TOSHIBA EXT'/Shows/My/'Doctor Who'/

              url0='DW s11e0'
              url1='DW s11e'

              for(( i=1; i<11; i++ ))
              do
              if ! [ $i -gt 9 ];
              then
              mkvmerge -o "$url0$i.mkv" "$url0$i.mkv" "$url0$i.srt" &&
              rm "$url0$i.srt"
              else
              mkvmerge -o "$url1$i.mkv" "$url1$i.mkv" "$url1$i.srt" &&
              rm "$url1$i.srt"
              fi
              done


              Note that I also added a && after each mkvmerge command so the rm only runs if the mkvmerge was successful. You don't want to delete the subtitle file if the merge failed!



              That said, although there's absolutely nothing wrong with your approach, I feel you could make it considerable simpler and more elegant using shell globbing instead:



              #!/bin/bash 

              for file in "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/"DW*mkv; do
              srtFile=${file//.mkv/.srt}
              mkvmerge -o "$file" "$file" "$srtFile" && rm "$srtFile"
              done


              You don't even need a script for this. You can just run it directly in the terminal as a one liner:



              for file in "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/"DW*mkv; do
              mkvmerge -o "$file" "$file" "${file//.mkv/.srt}" && rm "${file//.mkv/.srt}";
              done





              share|improve this answer


























                2












                2








                2






                You need to quote your variables. This should do what you want:



                #!/bin/bash 

                cd /media/ptrknvk/'TOSHIBA EXT'/Shows/My/'Doctor Who'/

                url0='DW s11e0'
                url1='DW s11e'

                for(( i=1; i<11; i++ ))
                do
                if ! [ $i -gt 9 ];
                then
                mkvmerge -o "$url0$i.mkv" "$url0$i.mkv" "$url0$i.srt" &&
                rm "$url0$i.srt"
                else
                mkvmerge -o "$url1$i.mkv" "$url1$i.mkv" "$url1$i.srt" &&
                rm "$url1$i.srt"
                fi
                done


                Note that I also added a && after each mkvmerge command so the rm only runs if the mkvmerge was successful. You don't want to delete the subtitle file if the merge failed!



                That said, although there's absolutely nothing wrong with your approach, I feel you could make it considerable simpler and more elegant using shell globbing instead:



                #!/bin/bash 

                for file in "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/"DW*mkv; do
                srtFile=${file//.mkv/.srt}
                mkvmerge -o "$file" "$file" "$srtFile" && rm "$srtFile"
                done


                You don't even need a script for this. You can just run it directly in the terminal as a one liner:



                for file in "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/"DW*mkv; do
                mkvmerge -o "$file" "$file" "${file//.mkv/.srt}" && rm "${file//.mkv/.srt}";
                done





                share|improve this answer














                You need to quote your variables. This should do what you want:



                #!/bin/bash 

                cd /media/ptrknvk/'TOSHIBA EXT'/Shows/My/'Doctor Who'/

                url0='DW s11e0'
                url1='DW s11e'

                for(( i=1; i<11; i++ ))
                do
                if ! [ $i -gt 9 ];
                then
                mkvmerge -o "$url0$i.mkv" "$url0$i.mkv" "$url0$i.srt" &&
                rm "$url0$i.srt"
                else
                mkvmerge -o "$url1$i.mkv" "$url1$i.mkv" "$url1$i.srt" &&
                rm "$url1$i.srt"
                fi
                done


                Note that I also added a && after each mkvmerge command so the rm only runs if the mkvmerge was successful. You don't want to delete the subtitle file if the merge failed!



                That said, although there's absolutely nothing wrong with your approach, I feel you could make it considerable simpler and more elegant using shell globbing instead:



                #!/bin/bash 

                for file in "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/"DW*mkv; do
                srtFile=${file//.mkv/.srt}
                mkvmerge -o "$file" "$file" "$srtFile" && rm "$srtFile"
                done


                You don't even need a script for this. You can just run it directly in the terminal as a one liner:



                for file in "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/"DW*mkv; do
                mkvmerge -o "$file" "$file" "${file//.mkv/.srt}" && rm "${file//.mkv/.srt}";
                done






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 1 hour ago

























                answered 1 hour ago









                terdon

                64.3k12136212




                64.3k12136212

























                    3














                    Quote variables to prevent word-splitting. By the way, double-quotes on a whole string is the preferred style.



                    #!/bin/bash

                    # Also exit if this fails
                    cd "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/" || exit

                    url0="DW s11e0"
                    url1="DW s11e"

                    for (( i=1; i<11; i++ )); do
                    # Also why use "not greater-than" when "less-than-or-equal" exists?
                    if [ $i -le 9 ]; then
                    # Also you can DRY* out this part with variables.
                    url="$url0"
                    else
                    url="$url1"
                    fi
                    # Also when concatenating variables, it's clearer to use the "${var}" style. **
                    f_mkv="${url}${i}.mkv"
                    f_srt="${url}${i}.srt"
                    mkvmerge -o "$f_mkv" "$f_mkv" "$f_srt"
                    rm "$f_srt"
                    done


                    Shellcheck is really useful for finding problems like this in shell scripts.



                    * DRY = Don't Repeat Yourself



                    ** Or you could use printf -v, but it's not a big improvement in this case. For example



                    printf -v f_mkv "%s%s.mkv" "$url" $i





                    share|improve this answer



















                    • 2




                      You may also wanna mention that using ${varname} style is better in cases where you are concatenating string with variable, so that the shell clearly knows what part of the token is a variable
                      – Sergiy Kolodyazhnyy
                      1 hour ago
















                    3














                    Quote variables to prevent word-splitting. By the way, double-quotes on a whole string is the preferred style.



                    #!/bin/bash

                    # Also exit if this fails
                    cd "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/" || exit

                    url0="DW s11e0"
                    url1="DW s11e"

                    for (( i=1; i<11; i++ )); do
                    # Also why use "not greater-than" when "less-than-or-equal" exists?
                    if [ $i -le 9 ]; then
                    # Also you can DRY* out this part with variables.
                    url="$url0"
                    else
                    url="$url1"
                    fi
                    # Also when concatenating variables, it's clearer to use the "${var}" style. **
                    f_mkv="${url}${i}.mkv"
                    f_srt="${url}${i}.srt"
                    mkvmerge -o "$f_mkv" "$f_mkv" "$f_srt"
                    rm "$f_srt"
                    done


                    Shellcheck is really useful for finding problems like this in shell scripts.



                    * DRY = Don't Repeat Yourself



                    ** Or you could use printf -v, but it's not a big improvement in this case. For example



                    printf -v f_mkv "%s%s.mkv" "$url" $i





                    share|improve this answer



















                    • 2




                      You may also wanna mention that using ${varname} style is better in cases where you are concatenating string with variable, so that the shell clearly knows what part of the token is a variable
                      – Sergiy Kolodyazhnyy
                      1 hour ago














                    3












                    3








                    3






                    Quote variables to prevent word-splitting. By the way, double-quotes on a whole string is the preferred style.



                    #!/bin/bash

                    # Also exit if this fails
                    cd "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/" || exit

                    url0="DW s11e0"
                    url1="DW s11e"

                    for (( i=1; i<11; i++ )); do
                    # Also why use "not greater-than" when "less-than-or-equal" exists?
                    if [ $i -le 9 ]; then
                    # Also you can DRY* out this part with variables.
                    url="$url0"
                    else
                    url="$url1"
                    fi
                    # Also when concatenating variables, it's clearer to use the "${var}" style. **
                    f_mkv="${url}${i}.mkv"
                    f_srt="${url}${i}.srt"
                    mkvmerge -o "$f_mkv" "$f_mkv" "$f_srt"
                    rm "$f_srt"
                    done


                    Shellcheck is really useful for finding problems like this in shell scripts.



                    * DRY = Don't Repeat Yourself



                    ** Or you could use printf -v, but it's not a big improvement in this case. For example



                    printf -v f_mkv "%s%s.mkv" "$url" $i





                    share|improve this answer














                    Quote variables to prevent word-splitting. By the way, double-quotes on a whole string is the preferred style.



                    #!/bin/bash

                    # Also exit if this fails
                    cd "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/" || exit

                    url0="DW s11e0"
                    url1="DW s11e"

                    for (( i=1; i<11; i++ )); do
                    # Also why use "not greater-than" when "less-than-or-equal" exists?
                    if [ $i -le 9 ]; then
                    # Also you can DRY* out this part with variables.
                    url="$url0"
                    else
                    url="$url1"
                    fi
                    # Also when concatenating variables, it's clearer to use the "${var}" style. **
                    f_mkv="${url}${i}.mkv"
                    f_srt="${url}${i}.srt"
                    mkvmerge -o "$f_mkv" "$f_mkv" "$f_srt"
                    rm "$f_srt"
                    done


                    Shellcheck is really useful for finding problems like this in shell scripts.



                    * DRY = Don't Repeat Yourself



                    ** Or you could use printf -v, but it's not a big improvement in this case. For example



                    printf -v f_mkv "%s%s.mkv" "$url" $i






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited 40 mins ago

























                    answered 1 hour ago









                    wjandrea

                    8,35842259




                    8,35842259








                    • 2




                      You may also wanna mention that using ${varname} style is better in cases where you are concatenating string with variable, so that the shell clearly knows what part of the token is a variable
                      – Sergiy Kolodyazhnyy
                      1 hour ago














                    • 2




                      You may also wanna mention that using ${varname} style is better in cases where you are concatenating string with variable, so that the shell clearly knows what part of the token is a variable
                      – Sergiy Kolodyazhnyy
                      1 hour ago








                    2




                    2




                    You may also wanna mention that using ${varname} style is better in cases where you are concatenating string with variable, so that the shell clearly knows what part of the token is a variable
                    – Sergiy Kolodyazhnyy
                    1 hour ago




                    You may also wanna mention that using ${varname} style is better in cases where you are concatenating string with variable, so that the shell clearly knows what part of the token is a variable
                    – Sergiy Kolodyazhnyy
                    1 hour ago


















                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Ask Ubuntu!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f1106116%2fdealing-with-space-in-file-links-using-bash%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Understanding the information contained in the Deep Space Network XML data?

                    Ross-on-Wye

                    Eastern Orthodox Church