Shortcut to `cd` into the 2nd folder in a directory












0















CONTEXT



I am in a directory with 3 folders.
After executing ls -1 they are ordered like so:



folder1
folder2
folder3


I want to quickly cd into folder2.



I was able to write a function to quickly cd into folder1



this is my function.



f1 () {
cd $(ls -d */|head -n 1)
}


QUESTION



I need a function called f2. That when executed, cds into folder2.





(the folders are sorted by ls -1. I am using zsh)










share|improve this question





























    0















    CONTEXT



    I am in a directory with 3 folders.
    After executing ls -1 they are ordered like so:



    folder1
    folder2
    folder3


    I want to quickly cd into folder2.



    I was able to write a function to quickly cd into folder1



    this is my function.



    f1 () {
    cd $(ls -d */|head -n 1)
    }


    QUESTION



    I need a function called f2. That when executed, cds into folder2.





    (the folders are sorted by ls -1. I am using zsh)










    share|improve this question



























      0












      0








      0








      CONTEXT



      I am in a directory with 3 folders.
      After executing ls -1 they are ordered like so:



      folder1
      folder2
      folder3


      I want to quickly cd into folder2.



      I was able to write a function to quickly cd into folder1



      this is my function.



      f1 () {
      cd $(ls -d */|head -n 1)
      }


      QUESTION



      I need a function called f2. That when executed, cds into folder2.





      (the folders are sorted by ls -1. I am using zsh)










      share|improve this question
















      CONTEXT



      I am in a directory with 3 folders.
      After executing ls -1 they are ordered like so:



      folder1
      folder2
      folder3


      I want to quickly cd into folder2.



      I was able to write a function to quickly cd into folder1



      this is my function.



      f1 () {
      cd $(ls -d */|head -n 1)
      }


      QUESTION



      I need a function called f2. That when executed, cds into folder2.





      (the folders are sorted by ls -1. I am using zsh)







      zsh cd-command






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Feb 11 at 11:59









      Anthony Geoghegan

      7,81253954




      7,81253954










      asked Feb 11 at 10:48









      Conor CosnettConor Cosnett

      1013




      1013






















          3 Answers
          3






          active

          oldest

          votes


















          5














          Shell globs are ordered in lexicographic order by default, and Zsh allows indexing the results of a glob directly, so you could do something like this:



          cd2() {
          cd -- */([2]); # indexing starts at one
          }


          In Bash, you could do the same with an array:



          cd2() {
          local dirs=(*/)
          cd -- "${dirs[1]}" # indexing starts at zero
          }


          Both essentially assume that there are at least two matches to the glob.
          See Kusalananda's answer for ways to deal with that assumption.



          Also, if you have ls aliased so that it's given some flags, the
          sort order might be different from that of the shells'. (I have ls aliased to ls -vF --color=auto on Linux, the -v changes even the sort order of a and _.) Zsh would of course give you multiple other options for sorting, too.





          Note that while you could use something like ls | head -2 | tail -1 to get the second filename in the list of ls output, that doesn't work for filenames with newlines and involves not one but three external processes to do something the shell is capable of doing itself, so it's not a very good solution. ls */ is even sillier, since here it's the shell that expands the glob, and ls just prints out the names it received. See https://mywiki.wooledge.org/ParsingLs for more about how relying on the output of ls can be problematic.






          share|improve this answer

































            3














            Using zsh, the following would cd into the second directory in the current directory:



            cd ./*(/[2])


            The / inside the parenthesis is a modifier of the * glob that makes it only match directory names (see the zshexpn manual), and [2] extract the second directory that this glob matches.



            Wrapping this in a function:



            cd2nd () { cd ./*(/[2]); }


            Note that this would take you to your home directory if there is no second directory in the current directory. We could protect against that by first testing whether the second directory exists:



            cd2nd () { [ -d ./*(/[2]) ] && cd ./*(/[2]); }


            But now we expand the pattern twice.



            In /bin/sh (or zsh), with only a single glob matching:



            cd2nd () { set -- ./*/; [ -d "$2" ] && cd "$2"; }


            This uses the positional parameters to hold all subdirectory names (*/ only matches directories), tests the second one for existence, and changes to that directory if it existed.






            share|improve this answer

































              1














              Function that takes argument with number of directory it should change to



              function ff()
              {
              cd "$(ls -d */ | head -n $1 | tail -n 1)";
              }


              Usage:



              user@localhost:~ $ ff 2
              user@localhost:~/Desktop $


              Explanation:





              • ls -d */ lists all directories in current directory


              • head -n $1 lists only $1 first directories, and $1 is our function argument, so if you call cc 2 then $1 would take value of 2 (first two lines are now being processed).


              • tail -n 1 picks only last line

              • All of this is being send to cd command, so directory is changed to proper one (quotes are there so directory names with spaces will be parsed as one argument)


              Warning!



              This version is assuming everything is ok with input. You should validate input (both from user and from filesystem directory list) to avoid unexpected errors in the future.






              share|improve this answer


























              • It would fail on any second directory name that contains whitespaces, and might do unexpected thing if there are directory names with shell globbing characters in their names (a directory called *, for example).

                – Kusalananda
                Feb 11 at 12:02











              • @Kusalananda: Thanks for pointing it out. Fixed with proper quotes and tested with directory names containing both spaces and special characters like '*'.

                – DevilaN
                Feb 11 at 18:09











              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%2f499908%2fshortcut-to-cd-into-the-2nd-folder-in-a-directory%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              5














              Shell globs are ordered in lexicographic order by default, and Zsh allows indexing the results of a glob directly, so you could do something like this:



              cd2() {
              cd -- */([2]); # indexing starts at one
              }


              In Bash, you could do the same with an array:



              cd2() {
              local dirs=(*/)
              cd -- "${dirs[1]}" # indexing starts at zero
              }


              Both essentially assume that there are at least two matches to the glob.
              See Kusalananda's answer for ways to deal with that assumption.



              Also, if you have ls aliased so that it's given some flags, the
              sort order might be different from that of the shells'. (I have ls aliased to ls -vF --color=auto on Linux, the -v changes even the sort order of a and _.) Zsh would of course give you multiple other options for sorting, too.





              Note that while you could use something like ls | head -2 | tail -1 to get the second filename in the list of ls output, that doesn't work for filenames with newlines and involves not one but three external processes to do something the shell is capable of doing itself, so it's not a very good solution. ls */ is even sillier, since here it's the shell that expands the glob, and ls just prints out the names it received. See https://mywiki.wooledge.org/ParsingLs for more about how relying on the output of ls can be problematic.






              share|improve this answer






























                5














                Shell globs are ordered in lexicographic order by default, and Zsh allows indexing the results of a glob directly, so you could do something like this:



                cd2() {
                cd -- */([2]); # indexing starts at one
                }


                In Bash, you could do the same with an array:



                cd2() {
                local dirs=(*/)
                cd -- "${dirs[1]}" # indexing starts at zero
                }


                Both essentially assume that there are at least two matches to the glob.
                See Kusalananda's answer for ways to deal with that assumption.



                Also, if you have ls aliased so that it's given some flags, the
                sort order might be different from that of the shells'. (I have ls aliased to ls -vF --color=auto on Linux, the -v changes even the sort order of a and _.) Zsh would of course give you multiple other options for sorting, too.





                Note that while you could use something like ls | head -2 | tail -1 to get the second filename in the list of ls output, that doesn't work for filenames with newlines and involves not one but three external processes to do something the shell is capable of doing itself, so it's not a very good solution. ls */ is even sillier, since here it's the shell that expands the glob, and ls just prints out the names it received. See https://mywiki.wooledge.org/ParsingLs for more about how relying on the output of ls can be problematic.






                share|improve this answer




























                  5












                  5








                  5







                  Shell globs are ordered in lexicographic order by default, and Zsh allows indexing the results of a glob directly, so you could do something like this:



                  cd2() {
                  cd -- */([2]); # indexing starts at one
                  }


                  In Bash, you could do the same with an array:



                  cd2() {
                  local dirs=(*/)
                  cd -- "${dirs[1]}" # indexing starts at zero
                  }


                  Both essentially assume that there are at least two matches to the glob.
                  See Kusalananda's answer for ways to deal with that assumption.



                  Also, if you have ls aliased so that it's given some flags, the
                  sort order might be different from that of the shells'. (I have ls aliased to ls -vF --color=auto on Linux, the -v changes even the sort order of a and _.) Zsh would of course give you multiple other options for sorting, too.





                  Note that while you could use something like ls | head -2 | tail -1 to get the second filename in the list of ls output, that doesn't work for filenames with newlines and involves not one but three external processes to do something the shell is capable of doing itself, so it's not a very good solution. ls */ is even sillier, since here it's the shell that expands the glob, and ls just prints out the names it received. See https://mywiki.wooledge.org/ParsingLs for more about how relying on the output of ls can be problematic.






                  share|improve this answer















                  Shell globs are ordered in lexicographic order by default, and Zsh allows indexing the results of a glob directly, so you could do something like this:



                  cd2() {
                  cd -- */([2]); # indexing starts at one
                  }


                  In Bash, you could do the same with an array:



                  cd2() {
                  local dirs=(*/)
                  cd -- "${dirs[1]}" # indexing starts at zero
                  }


                  Both essentially assume that there are at least two matches to the glob.
                  See Kusalananda's answer for ways to deal with that assumption.



                  Also, if you have ls aliased so that it's given some flags, the
                  sort order might be different from that of the shells'. (I have ls aliased to ls -vF --color=auto on Linux, the -v changes even the sort order of a and _.) Zsh would of course give you multiple other options for sorting, too.





                  Note that while you could use something like ls | head -2 | tail -1 to get the second filename in the list of ls output, that doesn't work for filenames with newlines and involves not one but three external processes to do something the shell is capable of doing itself, so it's not a very good solution. ls */ is even sillier, since here it's the shell that expands the glob, and ls just prints out the names it received. See https://mywiki.wooledge.org/ParsingLs for more about how relying on the output of ls can be problematic.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Feb 11 at 13:36

























                  answered Feb 11 at 10:54









                  ilkkachuilkkachu

                  59.9k996169




                  59.9k996169

























                      3














                      Using zsh, the following would cd into the second directory in the current directory:



                      cd ./*(/[2])


                      The / inside the parenthesis is a modifier of the * glob that makes it only match directory names (see the zshexpn manual), and [2] extract the second directory that this glob matches.



                      Wrapping this in a function:



                      cd2nd () { cd ./*(/[2]); }


                      Note that this would take you to your home directory if there is no second directory in the current directory. We could protect against that by first testing whether the second directory exists:



                      cd2nd () { [ -d ./*(/[2]) ] && cd ./*(/[2]); }


                      But now we expand the pattern twice.



                      In /bin/sh (or zsh), with only a single glob matching:



                      cd2nd () { set -- ./*/; [ -d "$2" ] && cd "$2"; }


                      This uses the positional parameters to hold all subdirectory names (*/ only matches directories), tests the second one for existence, and changes to that directory if it existed.






                      share|improve this answer






























                        3














                        Using zsh, the following would cd into the second directory in the current directory:



                        cd ./*(/[2])


                        The / inside the parenthesis is a modifier of the * glob that makes it only match directory names (see the zshexpn manual), and [2] extract the second directory that this glob matches.



                        Wrapping this in a function:



                        cd2nd () { cd ./*(/[2]); }


                        Note that this would take you to your home directory if there is no second directory in the current directory. We could protect against that by first testing whether the second directory exists:



                        cd2nd () { [ -d ./*(/[2]) ] && cd ./*(/[2]); }


                        But now we expand the pattern twice.



                        In /bin/sh (or zsh), with only a single glob matching:



                        cd2nd () { set -- ./*/; [ -d "$2" ] && cd "$2"; }


                        This uses the positional parameters to hold all subdirectory names (*/ only matches directories), tests the second one for existence, and changes to that directory if it existed.






                        share|improve this answer




























                          3












                          3








                          3







                          Using zsh, the following would cd into the second directory in the current directory:



                          cd ./*(/[2])


                          The / inside the parenthesis is a modifier of the * glob that makes it only match directory names (see the zshexpn manual), and [2] extract the second directory that this glob matches.



                          Wrapping this in a function:



                          cd2nd () { cd ./*(/[2]); }


                          Note that this would take you to your home directory if there is no second directory in the current directory. We could protect against that by first testing whether the second directory exists:



                          cd2nd () { [ -d ./*(/[2]) ] && cd ./*(/[2]); }


                          But now we expand the pattern twice.



                          In /bin/sh (or zsh), with only a single glob matching:



                          cd2nd () { set -- ./*/; [ -d "$2" ] && cd "$2"; }


                          This uses the positional parameters to hold all subdirectory names (*/ only matches directories), tests the second one for existence, and changes to that directory if it existed.






                          share|improve this answer















                          Using zsh, the following would cd into the second directory in the current directory:



                          cd ./*(/[2])


                          The / inside the parenthesis is a modifier of the * glob that makes it only match directory names (see the zshexpn manual), and [2] extract the second directory that this glob matches.



                          Wrapping this in a function:



                          cd2nd () { cd ./*(/[2]); }


                          Note that this would take you to your home directory if there is no second directory in the current directory. We could protect against that by first testing whether the second directory exists:



                          cd2nd () { [ -d ./*(/[2]) ] && cd ./*(/[2]); }


                          But now we expand the pattern twice.



                          In /bin/sh (or zsh), with only a single glob matching:



                          cd2nd () { set -- ./*/; [ -d "$2" ] && cd "$2"; }


                          This uses the positional parameters to hold all subdirectory names (*/ only matches directories), tests the second one for existence, and changes to that directory if it existed.







                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Feb 11 at 12:02

























                          answered Feb 11 at 11:01









                          KusalanandaKusalananda

                          132k17252416




                          132k17252416























                              1














                              Function that takes argument with number of directory it should change to



                              function ff()
                              {
                              cd "$(ls -d */ | head -n $1 | tail -n 1)";
                              }


                              Usage:



                              user@localhost:~ $ ff 2
                              user@localhost:~/Desktop $


                              Explanation:





                              • ls -d */ lists all directories in current directory


                              • head -n $1 lists only $1 first directories, and $1 is our function argument, so if you call cc 2 then $1 would take value of 2 (first two lines are now being processed).


                              • tail -n 1 picks only last line

                              • All of this is being send to cd command, so directory is changed to proper one (quotes are there so directory names with spaces will be parsed as one argument)


                              Warning!



                              This version is assuming everything is ok with input. You should validate input (both from user and from filesystem directory list) to avoid unexpected errors in the future.






                              share|improve this answer


























                              • It would fail on any second directory name that contains whitespaces, and might do unexpected thing if there are directory names with shell globbing characters in their names (a directory called *, for example).

                                – Kusalananda
                                Feb 11 at 12:02











                              • @Kusalananda: Thanks for pointing it out. Fixed with proper quotes and tested with directory names containing both spaces and special characters like '*'.

                                – DevilaN
                                Feb 11 at 18:09
















                              1














                              Function that takes argument with number of directory it should change to



                              function ff()
                              {
                              cd "$(ls -d */ | head -n $1 | tail -n 1)";
                              }


                              Usage:



                              user@localhost:~ $ ff 2
                              user@localhost:~/Desktop $


                              Explanation:





                              • ls -d */ lists all directories in current directory


                              • head -n $1 lists only $1 first directories, and $1 is our function argument, so if you call cc 2 then $1 would take value of 2 (first two lines are now being processed).


                              • tail -n 1 picks only last line

                              • All of this is being send to cd command, so directory is changed to proper one (quotes are there so directory names with spaces will be parsed as one argument)


                              Warning!



                              This version is assuming everything is ok with input. You should validate input (both from user and from filesystem directory list) to avoid unexpected errors in the future.






                              share|improve this answer


























                              • It would fail on any second directory name that contains whitespaces, and might do unexpected thing if there are directory names with shell globbing characters in their names (a directory called *, for example).

                                – Kusalananda
                                Feb 11 at 12:02











                              • @Kusalananda: Thanks for pointing it out. Fixed with proper quotes and tested with directory names containing both spaces and special characters like '*'.

                                – DevilaN
                                Feb 11 at 18:09














                              1












                              1








                              1







                              Function that takes argument with number of directory it should change to



                              function ff()
                              {
                              cd "$(ls -d */ | head -n $1 | tail -n 1)";
                              }


                              Usage:



                              user@localhost:~ $ ff 2
                              user@localhost:~/Desktop $


                              Explanation:





                              • ls -d */ lists all directories in current directory


                              • head -n $1 lists only $1 first directories, and $1 is our function argument, so if you call cc 2 then $1 would take value of 2 (first two lines are now being processed).


                              • tail -n 1 picks only last line

                              • All of this is being send to cd command, so directory is changed to proper one (quotes are there so directory names with spaces will be parsed as one argument)


                              Warning!



                              This version is assuming everything is ok with input. You should validate input (both from user and from filesystem directory list) to avoid unexpected errors in the future.






                              share|improve this answer















                              Function that takes argument with number of directory it should change to



                              function ff()
                              {
                              cd "$(ls -d */ | head -n $1 | tail -n 1)";
                              }


                              Usage:



                              user@localhost:~ $ ff 2
                              user@localhost:~/Desktop $


                              Explanation:





                              • ls -d */ lists all directories in current directory


                              • head -n $1 lists only $1 first directories, and $1 is our function argument, so if you call cc 2 then $1 would take value of 2 (first two lines are now being processed).


                              • tail -n 1 picks only last line

                              • All of this is being send to cd command, so directory is changed to proper one (quotes are there so directory names with spaces will be parsed as one argument)


                              Warning!



                              This version is assuming everything is ok with input. You should validate input (both from user and from filesystem directory list) to avoid unexpected errors in the future.







                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              edited Feb 11 at 18:07

























                              answered Feb 11 at 11:55









                              DevilaNDevilaN

                              561110




                              561110













                              • It would fail on any second directory name that contains whitespaces, and might do unexpected thing if there are directory names with shell globbing characters in their names (a directory called *, for example).

                                – Kusalananda
                                Feb 11 at 12:02











                              • @Kusalananda: Thanks for pointing it out. Fixed with proper quotes and tested with directory names containing both spaces and special characters like '*'.

                                – DevilaN
                                Feb 11 at 18:09



















                              • It would fail on any second directory name that contains whitespaces, and might do unexpected thing if there are directory names with shell globbing characters in their names (a directory called *, for example).

                                – Kusalananda
                                Feb 11 at 12:02











                              • @Kusalananda: Thanks for pointing it out. Fixed with proper quotes and tested with directory names containing both spaces and special characters like '*'.

                                – DevilaN
                                Feb 11 at 18:09

















                              It would fail on any second directory name that contains whitespaces, and might do unexpected thing if there are directory names with shell globbing characters in their names (a directory called *, for example).

                              – Kusalananda
                              Feb 11 at 12:02





                              It would fail on any second directory name that contains whitespaces, and might do unexpected thing if there are directory names with shell globbing characters in their names (a directory called *, for example).

                              – Kusalananda
                              Feb 11 at 12:02













                              @Kusalananda: Thanks for pointing it out. Fixed with proper quotes and tested with directory names containing both spaces and special characters like '*'.

                              – DevilaN
                              Feb 11 at 18:09





                              @Kusalananda: Thanks for pointing it out. Fixed with proper quotes and tested with directory names containing both spaces and special characters like '*'.

                              – DevilaN
                              Feb 11 at 18:09


















                              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%2f499908%2fshortcut-to-cd-into-the-2nd-folder-in-a-directory%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

                              How to reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

                              is 'sed' thread safe

                              How to make a Squid Proxy server?