bash shell中的快速目录导航


119

我想经常在完全不相关的路径(例如/Project/Warnest/docs/和)之间切换~/Dropbox/Projects/ds/test/

但是我不想一直打cd /[full-path]/。是否有任何快捷命令可以切换到以前使用的目录?

我能想到的一种解决方案是为我bash .profile的常用目录添加环境变量,并cd使用这些变量向它们添加环境变量。

但是还有其他解决方案吗?


符号链接也可能对此有用。en.wikipedia.org/wiki/...
user606723

Answers:



62

有一个shell变量CDPATHbash,并kshcdpathzsh

CDPATH    The search path for the cd command. This is a colon-separated
          list of directories in which the shell looks for destination
          directories specified by the cd command.

因此,您可以在〜/ .bashrc中进行设置:

export CDPATH=/Project/Warnest:~/Dropbox/Projects/ds

然后cd docscd test将带您到第一个找到的目录。(我的意思是,即使当前目录中存在一个具有相同名称的目录,CDPATH仍将对其进行查询。如果CDPATH将包含具有给定名称的子目录的更多目录,则将使用第一个目录。)


16
应该提到的是,一般来说,您希望第一个条目$CDPATH.(显式条目,即:也可以)。否则,您将得到奇怪的行为,即CDPATH目录优先于当前工作目录中的目录,而您可能不希望这样做。
jw013

4
我几乎做同样的事情,但是没有export。这样,CDPATH不会导出到具有潜在怪异或有害影响的脚本。有关更多讨论和示例,请参见此处
Telemachus,2012年

“ zsh中的bash,ksh和cdpath”……以及tcsh(仅在超级用户上基于该问题回答一个问题,并在SE上寻找类似答案时发现了这个问题)。
Hennes

我认为这是POSIX指定的。至少,POSIX for cd引用它。
mikeserv

48

您可能还会尝试使用一种称为autojump的工具。它保留了对其别名的调用数据库(j默认情况下),并尝试就要去的地方做出明智的决定。例如,如果您经常键入:

j ~/Pictures

您可以使用以下方法轻松到达那里:

j Pic

它可Debian和Ubuntu,以及包含在每个用户的基础上的~/.bashrc~/.zshrc默认。


5
Autojump可能是最好的工具,它会花一些时间来建立常见目录的数据库,但是一旦实现,我想您会发现没有它就无法生存。我知道每次我在别人的计算机上时都会感到残废。
quodlibetor 2012年

1
谢谢喜欢这个工具!尽管cd -知道您是否还很方便,但我认为这是比当前最佳答案更好的解决方案。
用户

全系统安装在什么系统上?
ctrl-alt-delor

1
@richard它可以作为软件包(例如,apt-get install autojump在Ubuntu中,也可以用于其页面上的许多其他软件包)用于系统范围的安装,但是每个用户都需要将其加载到其shell环境中,以便可以覆盖cd来跟踪您要去的地方
nealmcb

重要的一点source /usr/share/autojump/autojump.sh应该添加到〜/ .bashrc中,以使自动跳转工作
巴勃罗(Pablo)

39

如果目录数量很少,则可以使用pushd它们在目录之间进行轮换:

# starting point
$ pwd
/Project/Warnest/docs
# add second dir and change to it
$ pushd ~/Dropbox/Projects/ds/test
~/Dropbox/Projects/ds/test /Project/Warnest/docs
# prove we're in the right place
$ pwd
~/Dropbox/Projects/ds/test
# swap directories
$ pushd
/Project/Warnest/docs ~/Dropbox/Projects/ds/test

不像cd -,您可以在两个以上的目录中使用它


遵循Noach的建议,我现在使用的是:

function pd()
{
    if [[ $# -ge 1 ]];
    then
        choice="$1"
    else
        dirs -v
        echo -n "? "
        read choice
    fi
    if [[ -n $choice ]];
    then
        declare -i cnum="$choice"
        if [[ $cnum != $choice ]];
        then #choice is not numeric
            choice=$(dirs -v | grep $choice | tail -1 | awk '{print $1}')
            cnum="$choice"
            if [[ -z $choice || $cnum != $choice ]];
            then
                echo "$choice not found"
                return
            fi
        fi
        choice="+$choice"
    fi
    pushd $choice
}

用法示例:

# same as pushd +1
$ pd 1

# show a prompt, choose by number
$ pd
 0 ~/Dropbox/Projects/ds/test
 1 /Project/Warnest/docs
 2 /tmp
? 2
/tmp ~/Dropbox/Projects/ds/test /Project/Warnest/docs

# or choose by substring match
$ pd
 0 /tmp
 1 ~/Dropbox/Projects/ds/test
 2 /Project/Warnest/docs
? doc
/Project/Warnest/docs /tmp ~/Dropbox/Projects/ds/test

# substring without prompt
$ pd test
~/Dropbox/Projects/ds/test /Project/Warnest/docs /tmp

等等。显然,这只是为了在堆栈中旋转,并且不处理添加新路径-也许我应该重命名它。


6
哦,我知道pushd,并popd用于遍历,但不是说PUSHD可以轮播什么到目前为止使用...
Izkata

14

alias在bashrc中使用这些CD。
如:

alias wdoc='cd ~/Project/Warnest/docs'
alias dstest='cd ~/Dropbox/Projects/ds/test'

是bashrc是.profile之类的文件吗?我需要在其中添加这些行?
saiy2k 2012年

~/.bashrc/etc/bash.bashrc。我以前没有使用.profile过,所以不知道它们之间的关系:-(
Felix Yan

脚本bashrc将在您每次打开终端时启动。配置文件启动。

添加这些行到我.bash_profile,它的工作很棒.. thx :)
saiy2k 2012年

我定期访问几个特定的​​项目文件夹,这是设置和维护它们的最简单方法。同样,对我来说,这导致此处所有解决方案中键入的字符数绝对最少。吻!:-)
moodboom

11

我找到了一个脚本(通常称为acd_funch.sh)为我解决了此问题。有了它,您可以键入cd --以查看所使用的最后10个目录。它看起来像这样:

0  ~/Documents/onedir
1  ~/Music/anotherdir
2  ~/Music/thirddir
3  ~/etc/etc

~/Music/thirddir只需键入cd -2

参考文献

注意:此脚本最初发布在linux gazette文章中,该文章可在此处找到:acd_func.sh-扩展bash的CD以保留,显示和访问已访问目录名称的历史记录


2004年12月,在Linux公报第109期中也发布了相同的脚本。
Serge Stroobandt

@Dean链接转到音乐视频,并显示Geocities已关闭。
somethingSomething

1
@somethingSomething添加了备用链接。
2014年

历史| grep cd
user2180794

10

尝试使用cdable_varsbash中的shell选项。您可以使用打开它shopt -s cdable_vars

然后,您需要设置变量export dir1=/some/path。最后cd dir1,等等。然后,您可以将其放入其中~/.bashrc以使其粘住。


10

使用“ pushd -n ”(假设您使用bash)。

添加到您的〜/ .bashrc中:

pushd -n /Project/Warnest/docs/
pushd -n ~/Dropbox/Projects/ds/test/

然后,

cd ~ 在你家

cd ~1~/Dropbox/Projects/ds/test/

cd ~2/Project/Warnest/docs/

您可以使用~1~2以完全相同的方式等~


7

这里有很多好的建议。使用哪个取决于您是否有固定的目录切换列表,或者是否在寻找更通用的解决方案。

如果列表很小,那么设置简单的别名(如Felix Yan所建议)将最容易使用。

如果您正在寻找更通用的解决方案(即,许多不同的目录,随着时间的推移而变化),那么我将使用push和popd(如Useless建议)。我个人觉得默认的push / popd很难使用,尤其是当您开始在许多文件夹之间切换时;但是我写了一些调整,使我更轻松。将以下内容添加到您的bashrc中:

alias dirs='dirs -v'
pd () 
{ 
    if [ "$1" ]; then
        pushd "${1/#[0-9]*/+$1}";
    else
        pushd;
    fi > /dev/null
}
  • 使用pd(作为的缩写pushd)跳到一个新文件夹,记住您的位置。
  • 使用dirs查看保存的目录列表。
  • 使用pd 3跳转到电话号码3。

用法示例:

$ PS1='\w\$ '   ## just for demo purposes
~$ pd ~/Documents/data
~/Documents/data$ pd ../spec
~/Documents/spec$ pd ~/Dropbox/Public/
~/Dropbox/Public$ pd /tmp
/tmp$ pd /etc/defaults/
/etc/defaults$ dirs
 0  /etc/defaults
 1  /tmp
 2  ~/Dropbox/Public
 3  ~/Documents/spec
 4  ~/Documents/data
 5  ~
/etc/defaults$ pd 2
~/Dropbox/Public$ dirs
 0  ~/Dropbox/Public
 1  ~/Documents/spec
 2  ~/Documents/data
 3  ~
 4  /etc/defaults
 5  /tmp
~/Dropbox/Public$ pd 4
/etc/defaults$ dirs
 0  /etc/defaults
 1  /tmp
 2  ~/Dropbox/Public
 3  ~/Documents/spec
 4  ~/Documents/data
 5  ~
/etc/defaults$ pd 3
~/Documents/spec$ popd
~/Documents/data ~ /etc/defaults /tmp ~/Dropbox/Public
~/Documents/data$ 

6

以下内容似乎适用于我测试过的一种情况,您可以在〜/ Bookmarks中将目录名称作为符号链接删除:

mkdir "$HOME/Bookmarks"
ln -s /tmp "$HOME/Bookmarks/testdir"

function ccd() { cd $(readlink "$HOME/Bookmarks/$1") ; }

ccd testdir && echo $PWD
# gives /tmp

ccd()函数是否需要在终端提示或其他地方键入?您能解释一下吗?
saiy2k 2012年

1
@ saiy2k:对不起,是的。该function行进入您的.bashrc(您可以在终端中进行测试,但是当您关闭该窗口时该行将消失),设置“ testdir”测试用例之前的行将成为的名称/tmp,并且最后一行是测试,看它是否有效。
Ulrich Schwarz'2

6

您可能比尝试j2还要糟糕。

从自述文件:

在复杂的目录树上花很多时间CD-ing?

j跟踪您去过的地方以及在那里度过的时间,并提供了一种方便的方法来跳转到您实际使用的目录。

我广泛使用它并推荐它。


5

我建议使用zsh,该外壳可以很好地完成目录,文件甚至大多数cli程序的选项的TAB完成。

我已经使用该shell多年了,如果它消失了,我会想念它的功能。编写zsh脚本也很有趣,因为有大量的单行代码可以每天为您提供帮助。


由于bash具有相同的功能,因此无需更改为zsh即可完成TAB。对于其他功能,也许但并非如此。
Peer Stritzinger '02

1
@PeerStritzinger Bash在BASH 4.0中引入了这种功能,但是与zsh相比,它仍然远远落后。说“都一样”肯定是不正确的。
polemon '02

好吧,zsh无疑是übershell,但只需完成制表符就无需更改(询问bash的问题)。此外bash 4.0是大约3年前推出的
Peer Stritzinger

5

以我的经验,在shell中导航的最大加速是使用其历史搜索功能。在Bash中,您可以通过按Ctrl+ R并输入某种模式来向后搜索命令历史。然后,将该模式与历史记录中的先前条目进行匹配-可能是cd命令或其他操作-并在您键入内容时提出建议。只需按Enter键即可再次运行建议的命令。这reverse-search-history在Bash中被称为,我喜欢它。它为我节省了许多按键操作,并节省了内部内存。

这是一件好事,因为您只需要记住命令的一小部分,例如DropWa区分两个历史记录条目cd ~/Dropbox/Projects/ds/test/cd /Project/Warnest/docs/


5

我还使用了这些别名(将它们添加到〜/ .bashrc中):

alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias .....='cd ../../../..'

与它们一起进入上一级目录要快得多(不过它只能解决一半的导航问题)。


1
这些是有用的别名,但我不能完全确定它们是否可以满足OP的需求。您可能会考虑扩大答案,以建议这些答案如何直接对OP的问题有所帮助。
HalosGhost

4

如果您使用的是zsh:

  • 您不必键入cd,只需键入目录路径(/foo/bar/baz<Enter>等于cd /foo/bar/baz<Enter>

    需要auto_cd设置选项

  • 您可以使用Tab键扩展缩写路径(/u/sh/pi<Tab>扩展为/usr/share/pixmaps;也适用于文件名)

3
Bash 4获得了shopt -s autocd,因此不再仅是zsh。
吉尔斯

4

有一个相当不错的工具可以快速更改目录:

xd-eXtra快速目录 更改程序http://xd-home.sourceforge.net/xdman.html

有点尴尬的是,您需要将其映射到bash配置文件或类似文件中,因为它仅输出目录

# function to do `cd` using `xd`
# -g turns generalized directory search command processing on
# which improves the whole thing a bit
f() 
{
        cd `/usr/bin/xd -g $*`
}

您可以执行以下操作:

# change to /var/log/a* (gives you a list to choose from)    
f vla
# to skip the list and go directly to /var/log/apache2
f vlapach

将函数更改f() { cd "$(xd -g "$@")"; }为正确处理参数中的空格目录和空格xd(您可能不需要路径)。如果你从来没有使用xd以另一种方式,则可以选择做xd() { cd "$(command xd -g "$@")"; }(或者,使用/usr/bin/xd到位的command xd-你总是可以运行command xd …,如果你需要绕过它)。
亚当·卡兹

4

无论如何,您永远都不应在shell中键入完整路径。您始终可以使用:

soffice /P*/W*/*/mydoc*

代替

soffice /Project/Warnest/docs/mydoc.odt

1
这就像完成制表符一样,但在各个方面都更糟
Michael Mrozek

除非Project只是以P开头的文件,否则您不能使用制表符来完成相同数量的按键操作。此外,每次都必须等待完成,使用*无需等待。
gena2x

我认为您已经倒退了- P*除非Project是唯一一个以P开头的文件,否则您将无法做。制表符补全可以循环(默认情况下,在大多数Shell中;您需要将bb重新绑定到menu-completebash中),并在简单情况下立即解决像这样,没有等待的机会
Michael Mrozek

关于“您无法做到”-您可以尝试一下,如果您认为自己做不到,那您将失去全部要点。试试echo / u * / b * / g ++
gena2x

1
我理解您的意思,只要您确定键入的路径明确,它就会更快,但是/P*/W*/*/mydoc*听起来好像还可以,直到有一天您碰巧制作了另一个与该glob相匹配的文件,突然间结束了一次打开两个。/u*/*/g++几乎没有字符,但是希望我的任何根文件夹的子文件夹中的其他子都没有u命名为g++。(作为一个不错的折衷方案,在某些外壳中,您可以使用tab
随地扩展glob

3

还有OLDPWD一个环境变量,根据IEEE 1003.1(POSIX),每次cd更改工作目录时,都应使用先前的工作目录进行更新(对于好奇的环境变量,请参见IEEE 1003.1-2008第2506页的80244行)。




3

试试fastcd(https://github.com/frazenshtein/fastcd)它设置钩子,记录从bash访问的目录。并将脚本设置为“ j”别名,该脚本向您显示上次访问的目录,并具有快速cd(开始键入以过滤目录)的功能。需要对.bashrc进行修改才能使用“ j”别名。

获取工具

cd ~; mkdir Soft; cd Soft
git clone https://github.com/frazenshtein/fastcd

安装所需的模块

pip install --user urwid

将set.sh文件来源到您的bashrc中

echo -e "\nsource /home/$USER/Soft/fastcd/set.sh\n" >> ~/.bashrc

并更新bashrc

source ~/.bashrc

然后在控制台中输入“ j”


这是如何运作的?如果是别名,那么此工具为您做了什么,您无法通过手动编辑来完成.bashrc
G-Man

它启动守护程序,该守护程序在〜/ .fastcd中记录已启动的shell(bash)的访问目录。“ j”启动工具,该工具向您显示上次访问的目录,并具有快速cd的功能。需要对.bashrc进行修改才能使用“ j”别名。您可以查看源代码以获取更多信息,我想
Sam Toliman 2014年

谢谢你快速的回复。这就是答案中应该包含的信息。请修改您的答案以包含此信息。
G-Man

3

我有同样的问题,首先找到了这个答案。我安装了实用程序z(https://github.com/rupa/z)。

这正是您要寻找的,因为z从您的cd命令中学习,并根据频率原理(频率和最近)跟踪目录。因此,在一次执行两个cd命令之后,您可以执行以下操作:

z docs
z ds

分别跳到/Project/Warnest/docs/~/Dropbox/Projects/ds/test/。z的参数是正则表达式,因此您甚至不需要键入完整的文件夹名称。



2

多年来,我一直在使用自己的实用程序cdhist来管理它。它是cd命令的别名,并自动保留目录堆栈。


2

您可以export用来将目录路径分配给变量,然后引用它们。

export dir1=/Project/Warnest/docs/
export dir2= ~/Dropbox/Projects/ds/test/
cd $dir1
cd $dir2

是的,这足以满足一些最喜欢的顾客。无需安装任何其他实用程序。只需将export语句放入您的中~/.bashrc,它们将始终可用。
威斯巴基

1

这里的一些建议:

最直接的主意,我将在.profile文件中添加别名

vi ~/.profile
alias dir1='cd /myhome/onedir'
alias dir2='cd /jimmy/anotherdir'

然后使用 $ dir1dir2可以cd

如果您始终只切换两个目录。使用cd -将在它们之间切换。


1

我用于这种情况的解决方案是screen。开始屏幕并为每个目录创建一个窗口C-a c,然后在其中导航。使用C-a n或在Windows /目录之间切换C-a p。用命名窗口C-a A。然后,您可以使用弹出窗口列表,C-a "并使用窗口编号或窗口名称导航。由于是screen,您可以从会话中分离出来,以节省您的工作空间,并稍后使用相同的设置重新连接。


1

看来您基本上需要的是工作流程的项目文件。使用属于您的活动的目录,例如在编程IDE中。尝试使用Zsh导航工具n-cd那里的工具。它将允许您浏览上次访问的文件夹,并定义一个Hotlist带有您选择的目录的:

光盘

n-cd 可以绑定到以下组合键:

zle -N znt-cd-widget

bindkey“ ^ T” znt-cd-widget


1

TL; DR

  1. 使用的Fish用于交互的shell立即使您(fish> zsh> bash)。
  2. 使用POSIX/ Bash编写脚本,这是最广泛支持的语法(POSIX> Bash> Zsh> Fish)。

炮弹

在这里测试了不同的外壳是我的反馈(按照测试/采用的顺序):

  • Bash
    • 自动完成:基本;
    • 路径扩展:否;
    • 脚本:出色。
  • Zsh+ oh-my-zsh
    • 自动完成:良好(循环遍历);
    • 路径扩展:是(cd /e/x1cd /etc/X11/);
    • 脚本:很好。
  • Fish+ oh-my-fish(当前)是开箱即用的最佳选择:
    • 自动完成:本机和受支持的选项;
    • 路径扩展:是;
    • 脚本:与POSIX兼容差异太大。

使用有意义的别名

可以使用function和扩展每个shell alias,以下是我使用的与您的问题相关的(兼容POSIX):

back () {  # go to previous visited directory
        cd - || exit
}

up () {  # go to parent directory
        cd ..|| exit
}

有一些基本但真正有意义的内容,因此易于记住和自动完成。

了解你的外壳

配置CDPATH添加你最常用的目录(例如~/projects//etc/init.d/),这样你就可以快速跳转到它们。

有关更多信息,CDPATH请参见manatwork答案

环聊和阅读


当shell函数调用时exit,您退出了交互式shell。这些“有意义的别名”可能仅仅是alias back='cd -'alias up='cd ..'-但不要担心,这些命令将永远不会返回false,所以你永远不会退出(没有以前的目录发送您的家已经在根这是一个空操作?!?!) 。还请考虑alias back='cd $OLDPWD'(请注意单引号),因为它没有任何输出(cd -告诉您它将发送给您的位置,这可能是不必要的,因为您的提示中包含该信息)
Adam Katz

1

anc是cmd线工具(锚的缩写),用于保留目录的书签。(到目前为止仅通过bash测试)

在您的情况下:

anc a /Project/Warnest/docs/ ~/Dropbox/Projects/ds/test/

这将两个目录都添加到anchor(认为书签)列表中

现在,如果/Project/Warnest/docs/要从系统上的任何位置跳转到:

anc Warn

如果要跳转~/Dropbox/Projects/ds/test/输入:

anc ds test

除了将文本与已标记的路径匹配之外,anc还具有许多其他方便的方式来跳转目录。

anc i

启动交互模式,该模式按数字列出所有书签,因此您只需输入数字

如果输入:

anc Pro[TAB]

将显示一个与所有书签(在您的情况下为两个书签)匹配的列表,您可以使用箭头键从中进行选择,这是一种非常直观的方法。

在项目的github页面上获取anc:https : //github.com/tobimensch/anc

还有一个有关示例用法的自述文件。

完全公开:我是该脚本的作者。我希望有人会发现它有用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.