Shortcut to `cd` into the 2nd folder in a directory
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, cd
s into folder2
.
(the folders are sorted by ls -1
. I am using zsh
)
zsh cd-command
add a comment |
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, cd
s into folder2
.
(the folders are sorted by ls -1
. I am using zsh
)
zsh cd-command
add a comment |
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, cd
s into folder2
.
(the folders are sorted by ls -1
. I am using zsh
)
zsh cd-command
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, cd
s into folder2
.
(the folders are sorted by ls -1
. I am using zsh
)
zsh cd-command
zsh cd-command
edited Feb 11 at 11:59
Anthony Geoghegan
7,81253954
7,81253954
asked Feb 11 at 10:48
Conor CosnettConor Cosnett
1013
1013
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
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.
add a comment |
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.
add a comment |
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 callcc 2
then$1
would take value of2
(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.
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
add a comment |
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.
add a comment |
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.
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.
edited Feb 11 at 13:36
answered Feb 11 at 10:54
ilkkachuilkkachu
59.9k996169
59.9k996169
add a comment |
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
edited Feb 11 at 12:02
answered Feb 11 at 11:01
KusalanandaKusalananda
132k17252416
132k17252416
add a comment |
add a comment |
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 callcc 2
then$1
would take value of2
(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.
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
add a comment |
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 callcc 2
then$1
would take value of2
(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.
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
add a comment |
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 callcc 2
then$1
would take value of2
(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.
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 callcc 2
then$1
would take value of2
(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.
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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