Can you explain these three things in this bash code for me?












10















I have a function in my .bashrc file. I know what it does, it steps up X many directories with cd



Here it is:



up()
{
local d=""
limit=$1
for ((i=1 ; i <= limit ; i++))
do
d=$d/..
done
d=$(echo $d | sed 's/^///')
if [ -z "$d" ]; then
d=..
fi
cd $d
}


But can you explain these three things from it for me?




  1. d=$d/..

  2. sed 's/^///'

  3. d=..


Why not just do like this:



up()
{
limit=$1

for ((i=1 ; i <= limit ; i++))
do
cd ..
done
}


Usage:



<<<>>>~$ up 3
<<<>>>/$









share|improve this question





























    10















    I have a function in my .bashrc file. I know what it does, it steps up X many directories with cd



    Here it is:



    up()
    {
    local d=""
    limit=$1
    for ((i=1 ; i <= limit ; i++))
    do
    d=$d/..
    done
    d=$(echo $d | sed 's/^///')
    if [ -z "$d" ]; then
    d=..
    fi
    cd $d
    }


    But can you explain these three things from it for me?




    1. d=$d/..

    2. sed 's/^///'

    3. d=..


    Why not just do like this:



    up()
    {
    limit=$1

    for ((i=1 ; i <= limit ; i++))
    do
    cd ..
    done
    }


    Usage:



    <<<>>>~$ up 3
    <<<>>>/$









    share|improve this question



























      10












      10








      10


      2






      I have a function in my .bashrc file. I know what it does, it steps up X many directories with cd



      Here it is:



      up()
      {
      local d=""
      limit=$1
      for ((i=1 ; i <= limit ; i++))
      do
      d=$d/..
      done
      d=$(echo $d | sed 's/^///')
      if [ -z "$d" ]; then
      d=..
      fi
      cd $d
      }


      But can you explain these three things from it for me?




      1. d=$d/..

      2. sed 's/^///'

      3. d=..


      Why not just do like this:



      up()
      {
      limit=$1

      for ((i=1 ; i <= limit ; i++))
      do
      cd ..
      done
      }


      Usage:



      <<<>>>~$ up 3
      <<<>>>/$









      share|improve this question
















      I have a function in my .bashrc file. I know what it does, it steps up X many directories with cd



      Here it is:



      up()
      {
      local d=""
      limit=$1
      for ((i=1 ; i <= limit ; i++))
      do
      d=$d/..
      done
      d=$(echo $d | sed 's/^///')
      if [ -z "$d" ]; then
      d=..
      fi
      cd $d
      }


      But can you explain these three things from it for me?




      1. d=$d/..

      2. sed 's/^///'

      3. d=..


      Why not just do like this:



      up()
      {
      limit=$1

      for ((i=1 ; i <= limit ; i++))
      do
      cd ..
      done
      }


      Usage:



      <<<>>>~$ up 3
      <<<>>>/$






      shell sed variable function cd-command






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 10 hours ago









      Rui F Ribeiro

      41.3k1481140




      41.3k1481140










      asked Oct 18 '18 at 9:34









      somethingSomethingsomethingSomething

      1,792103259




      1,792103259






















          2 Answers
          2






          active

          oldest

          votes


















          24















          1. d=$d/.. adds /.. to the current contents of the d variable. d starts off empty, then the first iteration makes it /.., the second /../.. etc.


          2. sed 's/^///' drops the first /, so /../.. becomes ../.. (this can be done using a parameter expansion, d=${d#/}).



          3. d=.. only makes sense in the context of its condition:



            if [ -z "$d" ]; then
            d=..
            fi


            This ensures that, if d is empty at this point, you go to the parent directory. (up with no argument is equivalent to cd ...)




          This approach is better than iterative cd .. because it preserves cd - — the ability to return to the previous directory (from the user’s perspective) in one step.



          The function can be simplified:



          up() {
          local d=..
          for ((i = 1; i < ${1:-1}; i++)); do d=$d/..; done
          cd $d
          }


          This assumes we want to move up at least one level, and adds n - 1 levels, so we don’t need to remove the leading / or check for an empty $d.



          Using Athena jot (the athena-jot package in Debian):



          up() { cd $(jot -b .. -s / "${1:-1}"); }


          (based on a variant suggested by glenn jackman).






          share|improve this answer


























          • Yep, $OLDPWD getting trampled on came to mind. And on zsh with cd set to use the dirstack, that too.

            – muru
            Oct 18 '18 at 10:08











          • Is there some reason for assigning $1 to limit instead of just using $1 in the loop?

            – kundor
            Oct 18 '18 at 16:24






          • 1





            @kundor it ensures the default is 0 (see shell arithmetic). We could use ${1:-1} instead, as in glenn’s variant.

            – Stephen Kitt
            Oct 18 '18 at 16:37











          • @kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.

            – mtraceur
            Oct 18 '18 at 20:43



















          2















          But can you explain these three things from it for me?






          1. d=$d/..



            This concatenates the present contents of var d with /.. and assign it back to d.

            The end result is to make d a repeated string like /../../../...




          2. sed 's/^///'



            Remove the leading / from the string supplied, d (echo $d) in the code you posted.

            Probably better written as sed 's|^/||' to avoid the backslash.



            An alternative (faster and simpler) is to write d=${d#/}.




          3. d=..



            Assign the string .. to the var d.

            This only makes sense as a way to ensure that d has at least one .. in case the test if [ -z "$d" ]; then signals that the var d is empty.
            And that can only happen because the sed command is removing one character from d.

            If there is no need to remove the character from d, there is no need for sed or if.






          The code in your question will always move up at least one dir.



          Better





          • local d is enough to make sure that the variable is empty, nothing else is needed.

            However, local works only in some shells like bash or dash. In specific, ksh (as yash) doesn't have a local command. A more portable solution is:



            [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''



          • The for(( syntax is not portable. Better use something like:



            while [ "$((i+=1))" -lt "$limit" ]; do



          • Robust.

            If the values given to the function first argument could be negative or text, the function should be robust to process those values.

            First, lets limit the values to only numbers (I'll use c for count):



            c=${1%%[!0-9]*}


            And then limit the count value only to positive values:



            let "c = (c>0)?c:0"



          This function will hapily accept 0 or any text (without errors):



          up()
          {
          [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
          c=${1%%[!0-9]*}
          c=$(((c>0)?c:0))
          while [ "$((i+=1))" -le "$c" ]; do d="$d../"; done
          echo
          cd "${d%/}" # Removing the trailing / is not really needed for cd
          # but it is nice to know it could be done cleanly.
          }

          up 2
          up 0
          up asdf


          Remove the echo when you have tested the function.






          share|improve this answer

























            Your Answer








            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "106"
            };
            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: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            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%2funix.stackexchange.com%2fquestions%2f476253%2fcan-you-explain-these-three-things-in-this-bash-code-for-me%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









            24















            1. d=$d/.. adds /.. to the current contents of the d variable. d starts off empty, then the first iteration makes it /.., the second /../.. etc.


            2. sed 's/^///' drops the first /, so /../.. becomes ../.. (this can be done using a parameter expansion, d=${d#/}).



            3. d=.. only makes sense in the context of its condition:



              if [ -z "$d" ]; then
              d=..
              fi


              This ensures that, if d is empty at this point, you go to the parent directory. (up with no argument is equivalent to cd ...)




            This approach is better than iterative cd .. because it preserves cd - — the ability to return to the previous directory (from the user’s perspective) in one step.



            The function can be simplified:



            up() {
            local d=..
            for ((i = 1; i < ${1:-1}; i++)); do d=$d/..; done
            cd $d
            }


            This assumes we want to move up at least one level, and adds n - 1 levels, so we don’t need to remove the leading / or check for an empty $d.



            Using Athena jot (the athena-jot package in Debian):



            up() { cd $(jot -b .. -s / "${1:-1}"); }


            (based on a variant suggested by glenn jackman).






            share|improve this answer


























            • Yep, $OLDPWD getting trampled on came to mind. And on zsh with cd set to use the dirstack, that too.

              – muru
              Oct 18 '18 at 10:08











            • Is there some reason for assigning $1 to limit instead of just using $1 in the loop?

              – kundor
              Oct 18 '18 at 16:24






            • 1





              @kundor it ensures the default is 0 (see shell arithmetic). We could use ${1:-1} instead, as in glenn’s variant.

              – Stephen Kitt
              Oct 18 '18 at 16:37











            • @kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.

              – mtraceur
              Oct 18 '18 at 20:43
















            24















            1. d=$d/.. adds /.. to the current contents of the d variable. d starts off empty, then the first iteration makes it /.., the second /../.. etc.


            2. sed 's/^///' drops the first /, so /../.. becomes ../.. (this can be done using a parameter expansion, d=${d#/}).



            3. d=.. only makes sense in the context of its condition:



              if [ -z "$d" ]; then
              d=..
              fi


              This ensures that, if d is empty at this point, you go to the parent directory. (up with no argument is equivalent to cd ...)




            This approach is better than iterative cd .. because it preserves cd - — the ability to return to the previous directory (from the user’s perspective) in one step.



            The function can be simplified:



            up() {
            local d=..
            for ((i = 1; i < ${1:-1}; i++)); do d=$d/..; done
            cd $d
            }


            This assumes we want to move up at least one level, and adds n - 1 levels, so we don’t need to remove the leading / or check for an empty $d.



            Using Athena jot (the athena-jot package in Debian):



            up() { cd $(jot -b .. -s / "${1:-1}"); }


            (based on a variant suggested by glenn jackman).






            share|improve this answer


























            • Yep, $OLDPWD getting trampled on came to mind. And on zsh with cd set to use the dirstack, that too.

              – muru
              Oct 18 '18 at 10:08











            • Is there some reason for assigning $1 to limit instead of just using $1 in the loop?

              – kundor
              Oct 18 '18 at 16:24






            • 1





              @kundor it ensures the default is 0 (see shell arithmetic). We could use ${1:-1} instead, as in glenn’s variant.

              – Stephen Kitt
              Oct 18 '18 at 16:37











            • @kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.

              – mtraceur
              Oct 18 '18 at 20:43














            24












            24








            24








            1. d=$d/.. adds /.. to the current contents of the d variable. d starts off empty, then the first iteration makes it /.., the second /../.. etc.


            2. sed 's/^///' drops the first /, so /../.. becomes ../.. (this can be done using a parameter expansion, d=${d#/}).



            3. d=.. only makes sense in the context of its condition:



              if [ -z "$d" ]; then
              d=..
              fi


              This ensures that, if d is empty at this point, you go to the parent directory. (up with no argument is equivalent to cd ...)




            This approach is better than iterative cd .. because it preserves cd - — the ability to return to the previous directory (from the user’s perspective) in one step.



            The function can be simplified:



            up() {
            local d=..
            for ((i = 1; i < ${1:-1}; i++)); do d=$d/..; done
            cd $d
            }


            This assumes we want to move up at least one level, and adds n - 1 levels, so we don’t need to remove the leading / or check for an empty $d.



            Using Athena jot (the athena-jot package in Debian):



            up() { cd $(jot -b .. -s / "${1:-1}"); }


            (based on a variant suggested by glenn jackman).






            share|improve this answer
















            1. d=$d/.. adds /.. to the current contents of the d variable. d starts off empty, then the first iteration makes it /.., the second /../.. etc.


            2. sed 's/^///' drops the first /, so /../.. becomes ../.. (this can be done using a parameter expansion, d=${d#/}).



            3. d=.. only makes sense in the context of its condition:



              if [ -z "$d" ]; then
              d=..
              fi


              This ensures that, if d is empty at this point, you go to the parent directory. (up with no argument is equivalent to cd ...)




            This approach is better than iterative cd .. because it preserves cd - — the ability to return to the previous directory (from the user’s perspective) in one step.



            The function can be simplified:



            up() {
            local d=..
            for ((i = 1; i < ${1:-1}; i++)); do d=$d/..; done
            cd $d
            }


            This assumes we want to move up at least one level, and adds n - 1 levels, so we don’t need to remove the leading / or check for an empty $d.



            Using Athena jot (the athena-jot package in Debian):



            up() { cd $(jot -b .. -s / "${1:-1}"); }


            (based on a variant suggested by glenn jackman).







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Oct 18 '18 at 16:41

























            answered Oct 18 '18 at 10:05









            Stephen KittStephen Kitt

            175k24400477




            175k24400477













            • Yep, $OLDPWD getting trampled on came to mind. And on zsh with cd set to use the dirstack, that too.

              – muru
              Oct 18 '18 at 10:08











            • Is there some reason for assigning $1 to limit instead of just using $1 in the loop?

              – kundor
              Oct 18 '18 at 16:24






            • 1





              @kundor it ensures the default is 0 (see shell arithmetic). We could use ${1:-1} instead, as in glenn’s variant.

              – Stephen Kitt
              Oct 18 '18 at 16:37











            • @kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.

              – mtraceur
              Oct 18 '18 at 20:43



















            • Yep, $OLDPWD getting trampled on came to mind. And on zsh with cd set to use the dirstack, that too.

              – muru
              Oct 18 '18 at 10:08











            • Is there some reason for assigning $1 to limit instead of just using $1 in the loop?

              – kundor
              Oct 18 '18 at 16:24






            • 1





              @kundor it ensures the default is 0 (see shell arithmetic). We could use ${1:-1} instead, as in glenn’s variant.

              – Stephen Kitt
              Oct 18 '18 at 16:37











            • @kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.

              – mtraceur
              Oct 18 '18 at 20:43

















            Yep, $OLDPWD getting trampled on came to mind. And on zsh with cd set to use the dirstack, that too.

            – muru
            Oct 18 '18 at 10:08





            Yep, $OLDPWD getting trampled on came to mind. And on zsh with cd set to use the dirstack, that too.

            – muru
            Oct 18 '18 at 10:08













            Is there some reason for assigning $1 to limit instead of just using $1 in the loop?

            – kundor
            Oct 18 '18 at 16:24





            Is there some reason for assigning $1 to limit instead of just using $1 in the loop?

            – kundor
            Oct 18 '18 at 16:24




            1




            1





            @kundor it ensures the default is 0 (see shell arithmetic). We could use ${1:-1} instead, as in glenn’s variant.

            – Stephen Kitt
            Oct 18 '18 at 16:37





            @kundor it ensures the default is 0 (see shell arithmetic). We could use ${1:-1} instead, as in glenn’s variant.

            – Stephen Kitt
            Oct 18 '18 at 16:37













            @kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.

            – mtraceur
            Oct 18 '18 at 20:43





            @kundor Also human readability. A well-named variable tells you what the intended meaning or purpose of the first argument is when you start reading the function, without having to first know what the function does or finish understanding the code to deduce it.

            – mtraceur
            Oct 18 '18 at 20:43













            2















            But can you explain these three things from it for me?






            1. d=$d/..



              This concatenates the present contents of var d with /.. and assign it back to d.

              The end result is to make d a repeated string like /../../../...




            2. sed 's/^///'



              Remove the leading / from the string supplied, d (echo $d) in the code you posted.

              Probably better written as sed 's|^/||' to avoid the backslash.



              An alternative (faster and simpler) is to write d=${d#/}.




            3. d=..



              Assign the string .. to the var d.

              This only makes sense as a way to ensure that d has at least one .. in case the test if [ -z "$d" ]; then signals that the var d is empty.
              And that can only happen because the sed command is removing one character from d.

              If there is no need to remove the character from d, there is no need for sed or if.






            The code in your question will always move up at least one dir.



            Better





            • local d is enough to make sure that the variable is empty, nothing else is needed.

              However, local works only in some shells like bash or dash. In specific, ksh (as yash) doesn't have a local command. A more portable solution is:



              [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''



            • The for(( syntax is not portable. Better use something like:



              while [ "$((i+=1))" -lt "$limit" ]; do



            • Robust.

              If the values given to the function first argument could be negative or text, the function should be robust to process those values.

              First, lets limit the values to only numbers (I'll use c for count):



              c=${1%%[!0-9]*}


              And then limit the count value only to positive values:



              let "c = (c>0)?c:0"



            This function will hapily accept 0 or any text (without errors):



            up()
            {
            [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
            c=${1%%[!0-9]*}
            c=$(((c>0)?c:0))
            while [ "$((i+=1))" -le "$c" ]; do d="$d../"; done
            echo
            cd "${d%/}" # Removing the trailing / is not really needed for cd
            # but it is nice to know it could be done cleanly.
            }

            up 2
            up 0
            up asdf


            Remove the echo when you have tested the function.






            share|improve this answer






























              2















              But can you explain these three things from it for me?






              1. d=$d/..



                This concatenates the present contents of var d with /.. and assign it back to d.

                The end result is to make d a repeated string like /../../../...




              2. sed 's/^///'



                Remove the leading / from the string supplied, d (echo $d) in the code you posted.

                Probably better written as sed 's|^/||' to avoid the backslash.



                An alternative (faster and simpler) is to write d=${d#/}.




              3. d=..



                Assign the string .. to the var d.

                This only makes sense as a way to ensure that d has at least one .. in case the test if [ -z "$d" ]; then signals that the var d is empty.
                And that can only happen because the sed command is removing one character from d.

                If there is no need to remove the character from d, there is no need for sed or if.






              The code in your question will always move up at least one dir.



              Better





              • local d is enough to make sure that the variable is empty, nothing else is needed.

                However, local works only in some shells like bash or dash. In specific, ksh (as yash) doesn't have a local command. A more portable solution is:



                [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''



              • The for(( syntax is not portable. Better use something like:



                while [ "$((i+=1))" -lt "$limit" ]; do



              • Robust.

                If the values given to the function first argument could be negative or text, the function should be robust to process those values.

                First, lets limit the values to only numbers (I'll use c for count):



                c=${1%%[!0-9]*}


                And then limit the count value only to positive values:



                let "c = (c>0)?c:0"



              This function will hapily accept 0 or any text (without errors):



              up()
              {
              [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
              c=${1%%[!0-9]*}
              c=$(((c>0)?c:0))
              while [ "$((i+=1))" -le "$c" ]; do d="$d../"; done
              echo
              cd "${d%/}" # Removing the trailing / is not really needed for cd
              # but it is nice to know it could be done cleanly.
              }

              up 2
              up 0
              up asdf


              Remove the echo when you have tested the function.






              share|improve this answer




























                2












                2








                2








                But can you explain these three things from it for me?






                1. d=$d/..



                  This concatenates the present contents of var d with /.. and assign it back to d.

                  The end result is to make d a repeated string like /../../../...




                2. sed 's/^///'



                  Remove the leading / from the string supplied, d (echo $d) in the code you posted.

                  Probably better written as sed 's|^/||' to avoid the backslash.



                  An alternative (faster and simpler) is to write d=${d#/}.




                3. d=..



                  Assign the string .. to the var d.

                  This only makes sense as a way to ensure that d has at least one .. in case the test if [ -z "$d" ]; then signals that the var d is empty.
                  And that can only happen because the sed command is removing one character from d.

                  If there is no need to remove the character from d, there is no need for sed or if.






                The code in your question will always move up at least one dir.



                Better





                • local d is enough to make sure that the variable is empty, nothing else is needed.

                  However, local works only in some shells like bash or dash. In specific, ksh (as yash) doesn't have a local command. A more portable solution is:



                  [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''



                • The for(( syntax is not portable. Better use something like:



                  while [ "$((i+=1))" -lt "$limit" ]; do



                • Robust.

                  If the values given to the function first argument could be negative or text, the function should be robust to process those values.

                  First, lets limit the values to only numbers (I'll use c for count):



                  c=${1%%[!0-9]*}


                  And then limit the count value only to positive values:



                  let "c = (c>0)?c:0"



                This function will hapily accept 0 or any text (without errors):



                up()
                {
                [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
                c=${1%%[!0-9]*}
                c=$(((c>0)?c:0))
                while [ "$((i+=1))" -le "$c" ]; do d="$d../"; done
                echo
                cd "${d%/}" # Removing the trailing / is not really needed for cd
                # but it is nice to know it could be done cleanly.
                }

                up 2
                up 0
                up asdf


                Remove the echo when you have tested the function.






                share|improve this answer
















                But can you explain these three things from it for me?






                1. d=$d/..



                  This concatenates the present contents of var d with /.. and assign it back to d.

                  The end result is to make d a repeated string like /../../../...




                2. sed 's/^///'



                  Remove the leading / from the string supplied, d (echo $d) in the code you posted.

                  Probably better written as sed 's|^/||' to avoid the backslash.



                  An alternative (faster and simpler) is to write d=${d#/}.




                3. d=..



                  Assign the string .. to the var d.

                  This only makes sense as a way to ensure that d has at least one .. in case the test if [ -z "$d" ]; then signals that the var d is empty.
                  And that can only happen because the sed command is removing one character from d.

                  If there is no need to remove the character from d, there is no need for sed or if.






                The code in your question will always move up at least one dir.



                Better





                • local d is enough to make sure that the variable is empty, nothing else is needed.

                  However, local works only in some shells like bash or dash. In specific, ksh (as yash) doesn't have a local command. A more portable solution is:



                  [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''



                • The for(( syntax is not portable. Better use something like:



                  while [ "$((i+=1))" -lt "$limit" ]; do



                • Robust.

                  If the values given to the function first argument could be negative or text, the function should be robust to process those values.

                  First, lets limit the values to only numbers (I'll use c for count):



                  c=${1%%[!0-9]*}


                  And then limit the count value only to positive values:



                  let "c = (c>0)?c:0"



                This function will hapily accept 0 or any text (without errors):



                up()
                {
                [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
                c=${1%%[!0-9]*}
                c=$(((c>0)?c:0))
                while [ "$((i+=1))" -le "$c" ]; do d="$d../"; done
                echo
                cd "${d%/}" # Removing the trailing / is not really needed for cd
                # but it is nice to know it could be done cleanly.
                }

                up 2
                up 0
                up asdf


                Remove the echo when you have tested the function.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Oct 18 '18 at 22:54

























                answered Oct 18 '18 at 22:13









                IsaacIsaac

                12k11852




                12k11852






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Unix & Linux Stack Exchange!


                    • 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%2funix.stackexchange.com%2fquestions%2f476253%2fcan-you-explain-these-three-things-in-this-bash-code-for-me%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

                    Loup dans la culture

                    How to solve the problem of ntp “Unable to contact time server” from KDE?

                    Connection limited (no internet access)