为什么更改目录时通配符 * 不起作用?

为什么更改目录时通配符 * 不起作用?

例如我在我的目录中:

/home/myname

然后我想将 CD 放入另一个目录。

/home/pulsar/... 

由于我需要深入到其他目录,如何才能在不必输入整行的情况下进行此操作?我试过

cd */thedirectoryiwanttogointo

但这行不通。我必须输入整行。

答案1

您的通配符可能不起作用,因为:

  • 您提供的位置中没有与通配符匹配的内容,或者
  • 不止一场比赛。

在子目录之间频繁移动的常用方法(在 shell 中)是使用该CDPATH功能以及pushdpopd

CDPATH功能(可能首先出现在 tcsh 中)是一个以冒号分隔的目录列表。如果您名字的父代thedirectoryiwanttogointo相当唯一,那么您可以将父代添加到列表中。

如需进一步阅读(您的 shell 手册页应该位于第一个):

pushdpopd更新CDPATH,但仍可以追溯到 20 世纪 90 年代中期。它们允许您在各自的命令期间保存当前目录(“推入”堆栈)并恢复它(从堆栈“弹出”)cd。进一步阅读:

其他人使用 shell 别名或符号链接。这些在前往知名地点时最有用。

答案2

假设所有可能的目标目录都在下面/home,并且目录名称中没有换行符,您可以使用以下 shell 函数:

cds() {
    cd "$(find /home -type d -name "$1" | head -n 1)"
}

$ cds thedirectoryiwanttogointo

当然,根据子目录和文件的数量/home以及操作系统是否在内存中缓存所有树的能力,性能会有很大差异。

在 GNU 系统上,您可以使用以下语法来加快速度并使其对于文件名中的换行符更可靠:

cds() {
    cd "$(find /home -type d -name "$1" -print -quit)"
}

一旦找到第一个匹配项,就会停止搜索。

请注意,参数被视为一种模式,因此您可以执行以下操作:

cds 'foo*bar'

例如cd进入第一个目录(未指定顺序),其名称以 . 开头foo并以 . 结尾bar

答案3

您希望通过通配符扩展来查找系统上任何位置的路径。如果正确指定模式,您可以做到这一点:

cd /**/thedirectoryiwanttogointo

默认情况下可以在 zsh 和 Fish 中工作,如果你首先在 Bash 中shopt -s globstar, 在tcsh 如果你set globstar,在ksh93中如果你set -o globstar,在yash如果你set -o extended-glob

这是有效的,因为通配符在以 开头的绝对路径中使用,而/不是相对于当前目录,并且当您选择使用该**模式时,它会扩展到任意数量的子目录。

虽然这会起作用,可能需要很长时间。您的 shell 必须在整个系统中搜索匹配的文件。您可以通过提供更长的前缀来减少更多的搜索空间:

cd /home/pulsar/**/thedirectoryiwanttogointo/

钻得越深,需要做的搜索就越少。如果目录树相当稀疏,这不会花费太长时间并且实际上很实用。尾随/确保扩展仅针对目录,这消除了可能发生的各种歧义。

如果仍有多个匹配项,结果将取决于您的 shell。 Bash 和 Fish 将切换到按字母顺序排列的第一个匹配,忽略歧义。 tcsh和yash会报错。 zsh 和 ksh 会将其解释为尝试使用其高级目录切换功能之一,并且大概报告错误。


如果您可能会重复使用同一目录,请将父目录放在进入CDPATH$FOO或者创建一个可以用来代替长路径的shell 变量是更好的选择。**如果您经常使用shell 变量,则可以将其与扩展结合起来以节省更多输入。

答案4

如果您总是访问同一个深层目录,一个简单的解决方案就是创建一个指向它的符号链接:

ln -s ~/foo/bar/baz/quux/etc/etc/etc/target ~/shortcut

如果您以前访问过该目录,另一个解决方案是在命令历史记录中搜索您想要的名称;按 ctrl-R 和要搜索的字符。这是 bash 特有的,但我想大多数现代 shell 都有类似的功能。

相关内容