语境
我所在的目录有 3 个文件夹。执行后,ls -1
它们的顺序如下:
folder1
folder2
folder3
我想快点cd
进入folder2
。
我能够快速编写一个cd
函数folder1
这是我的职责。
f1 () {
cd $(ls -d */|head -n 1)
}
问题
我需要一个名为 的函数f2
。执行时,cd
s 进入folder2
.
(文件夹按 排序ls -1
。我正在使用zsh
)
答案1
默认情况下,Shell glob 按字典顺序排序,并且 Zsh 允许直接索引 glob 的结果,因此您可以执行以下操作:
cd2() {
cd -- */([2]); # indexing starts at one
}
在 Bash 中,您可以对数组执行相同的操作:
cd2() {
local dirs=(*/)
cd -- "${dirs[1]}" # indexing starts at zero
}
两者本质上都假设至少有两个与全局匹配的项。看拘萨罗南达的回答了解处理该假设的方法。
另外,如果您使用ls
别名以便给它一些标志,则排序顺序可能与 shell 的排序顺序不同。 (我在 Linux 上使用了ls
别名,甚至更改了和的排序顺序。)Zsh 当然也会为您提供多种其他排序选项。ls -vF --color=auto
-v
a
_
请注意,虽然你可以使用类似于ls | head -2 | tail -1
获取输出列表中的第二个文件名的方法ls
,这对于带有换行符的文件名不起作用,并且涉及不是一个而是三个外部进程来执行 shell 能够自行执行的操作,因此这不是一个很好的解决方案。ls */
更愚蠢的是,因为这里是壳它扩展了 glob,并且ls
只打印出它收到的名称。看https://mywiki.wooledge.org/ParsingLs了解更多关于依赖 的输出ls
可能会出现问题的信息。
答案2
使用zsh
,以下内容将cd
进入当前目录中的第二个目录:
cd ./*(/[2])
/
括号内是 glob 的修饰符,*
使其仅匹配目录名称(请参阅手册zshexpn
),并[2]
提取此 glob 匹配的第二个目录。
将其包装在一个函数中:
cd2nd () { cd ./*(/[2]); }
请注意,如果当前目录中没有第二个目录,这会将您带到主目录。我们可以通过首先测试第二个目录是否存在来防止这种情况:
cd2nd () { [ -d ./*(/[2]) ] && cd ./*(/[2]); }
但现在我们扩大模式两次。
在/bin/sh
(or zsh
) 中,只有一个全局匹配:
cd2nd () { set -- ./*/; [ -d "$2" ] && cd "$2"; }
这使用位置参数来保存所有子目录名称(*/
仅匹配目录),测试第二个子目录是否存在,并更改该目录(如果存在)。
答案3
接受参数及其应更改为的目录号的函数
function ff()
{
cd "$(ls -d */ | head -n $1 | tail -n 1)";
}
用法:
user@localhost:~ $ ff 2
user@localhost:~/Desktop $
解释:
ls -d */
列出当前目录下的所有目录head -n $1
仅列出$1
第一个目录,并且$1
是我们的函数参数,因此如果您调用cc 2
then$1
将取值2
(前两行现在正在处理)。tail -n 1
只选择最后一行- 所有这些都被发送到
cd
命令,因此目录被更改为正确的目录(其中有引号,因此带有空格的目录名称将被解析为一个参数)
警告!
此版本假设输入一切正常。您应该验证输入(来自用户和文件系统目录列表)以避免将来出现意外错误。