如何使用 bash 更快地导航目录

1,008 阅读4分钟

本文译自: Max J. Hoffmann

How to navigate directories faster with bash

作为一名知识工作者,在我的日常工作中,更改目录 是一项极其频繁的操作,我从终端运行计算、分析数据和开发代码。事实上,更改目录是在不同任务、上下文或工作空间之间行走的基本操作模式。

当我第一次开始使用终端时,我唯一知道的命令是cd,但多年来我学到了 bash 引擎下还有很多命令,这些命令可以大大减少了更改目录所需的时间。下面我将分享五个我经常使用的,切换目录的技巧。它们不仅帮助我更快地切换目录,而且还减少了记住长子目录的认知负担。

此外,为了最大限度地提高效率,我将所有技巧结合起来使用,我希望它们也能让您更高效。

最强输出 cd

本技巧仅侧重于使用cd命令的所有功能。使用cd最常见的形式是:

cd directory

其中directory可以是./relative(相对当前目录的相对路径)或/absolute(相对根目录的绝对路径)。同样众所周知的是..是当前目录的上级目录的别名,../..上级的上级等以此类推。也许不太为人所知的是~它表示一个人的主目录。不过跳转个人主目录最直接的方法是,省略directory参数,像下面这样直接使用cd

cd 

此外-当前目录的上一个目录。所以cd -就像cd的后退按钮,它只适用于历史上的一个步骤。使用cd -重复在两个目录之间切换。

我还发现可以给cd ..定义别名:

alias ..="cd .."

像上面这样定义后,就可以使用..代替cd ..,当然cd ..依然有效

补充以下:

alias ..="cd .."
alias ...="cd ../.."
alias ....="cd ../../.."
alias .....="cd ../../../.."
alias ......="cd ../../../../.."
alias .......="cd ../../../../../.."
alias ........="cd ../../../../../../.."
alias .........="cd ../../../../../../../.."
alias ..........="cd ../../../../../../../../.."
alias ...........="cd ../../../../../../../../../.."
alias ............="cd ../../../../../../../../../../.."
alias .............="cd ../../../../../../../../../../../.."

当目录过长是,像上面这样定义了别名,就只需添加点 (...) 即可显示更多目录。

另一个简洁的指令是!$,它是前一个命令的最后一个参数的别名。如果您创建了一个新目录并不想再次输入目录名称直接进入该目录时,这会很方便。操作命令如下:

mkdir -p make/new/directory
cd !$

为您的工作流程配置 $CDPATH

下一个技巧是有效使用CDPATH变量。几乎每个使用 shell 的人都熟悉PATH变量的重要性。PATH变量意味着,每当输入命令时,shell 将查找路径中列出的目录,搜索可执行文件,然后按照路径中列出的顺序执行它找到的第一个可执行文件命名命令。

因此,有一个密切相关的变量名为CDPATH,它是cd的模拟变量。当你输入

cd directory

cd将搜索CDPATH中列出的所有目录,并跳转到按CDPATH中列出的顺序找到的第一个目录。默认设置为CDPATH=.,这意味着cd只搜索当前工作目录。但是不会就此停止。我的~/.bashrc包含 export CDPATH=.::/src:/calculations:/ssh_mounts

有了这一行代码,我就可以直接跳转到当前目录下的任何目录,主目录、指定目录src的软件项目、calculations和可能链接到通过sshfs的程序链接的其他服务器的名为ssh_mounts的目录。

这有助于分开不同类型活动的目录,同时还允许在它们之间进行快速更改。如果~/.bashrc所有用户账户只有一个,并使用git和 bash完成等方式对其进行同步,它会更强大.

if [ -f /etc/bash_completion ]; then
  . /etc/bash_completion
elif [ -f /opt/local/etc/profile.d/bash_completion.sh ]; then
  . /opt/local/etc/profile.d/bash_completion.sh
fi

另一个简洁的 bash 选项是

shopt -s cdspell // 开启cd拼写检查

它会自动更正目录名称中的小错误,并跳转到现有目录的最佳猜测。或者

complete -d cd  

这将实现在输入cd后按tab键,仅以建议目录。

使用 pushd/popd 加速 cd

另一个比cd名气小一点的命令是pushdpopd。 pushd推送目录,它会更改当前工作目录,但也会将留下的目录 推送 到历史堆栈中。 popd是另一种意思,指 弹出目录,它从历史堆栈中 弹出 最后访问的目录。命令dirs会列出当前堆叠在历史记录上的目录。像经过一下操作,

pushd a
pushd b
pushd c
popd

将带你到目录b

下面的截图是我自己测试的结果,我每执行一次pushd命令,就会跳转对应的目录,并且会打印出当前堆叠在历史记录上的目录。

image.png

pushdpopd是两个非常棒的命令,它们在脚本中非常有用,可以在 shell 脚本中准确地进入和退出目录。唯一的问题是为什么要输入这么多字符,为什么cd没有内置该功能。要解决此问题,请将以下两个函数放入覆盖cd~/.bashrc中:

function cd() {
  if [ "$#" = "0" ]
  then
  pushd ${HOME} > /dev/null
  elif [ -f "${1}" ]
  then
    ${EDITOR} ${1}
  else
  pushd "$1" > /dev/null
  fi
}

function bd(){
  if [ "$#" = "0" ]
  then
    popd > /dev/null
  else
    for i in $(seq ${1})
    do
      popd > /dev/null
    done
  fi
}

这些功能中的另一层含义是:

  • 除了popd,你也可以使用bd进行back directory
  • bd还接受一个数字n作为参数,让您n一次后退目录;
  • 如果cd参数是一个文件而不是一个目录,它会假设您想将它编辑为文本文件并在您喜欢的编辑器中打开它。

您仍然可以使用dirs列出历史记录并根据您的喜好调整上述功能。

lf = 最新文件

有了像这样的别名后,我开始思考。当我输入ls检查当前目录的内容,并决定是否要移动到子目录之一时:为什么我必须再次输入它(目录名或目录名部分内容至少足以让 Tab 完成工作),即使目录名称已经屏幕上?

alias lln="ls -lhtr  --time-style long-iso | tac | cat -n | tac | sed -s 's/^\s*([0-9]*)\s*(.*)/[\1]  \2 [\1]/'g && pwd"
function lf() {
    if [ "x${1}" == "x" ]
    then
        n=1 
    else
        n="${1}"
    fi  
    ls -rt1 | tail -n ${n} | head -n 1
}

现在,输入lln将显示按时间排序的当前目录的内容,最新的文件在底部。但是你也会注意到每一行的两侧都有一个索引,从最新的文件 1 开始。现在输入

lf 1

lf(1 是默认参数)将生成分配给索引一的文件名。如果这是一个目录,我可以发出cd $(lf 1)更改到最新目录的命令。当然,我可以将lf与任何其他命令组合,例如

vi $(lf 3)

或者

python $(lf 5)

更有效地切换历史

最后一个技巧旨在更快地从历史记录中检索命令。通常,向上箭头会跳转到历史记录中的上一个命令。但是,如果在历史记录中跳过 5 或 10 条或更多命令,这很快就会变得非常乏味。相反,如果你把下面这段代码输入您的/.bashrc

bind '"\e[A":history-search-backward'
bind '"\e[B":history-search-forward'

然后开始键入命令的一部分,再使用箭头跳转,它只会跳转到历史记录中有相同开头的那些命令。这对任何命令行工作都很有用,您可能已经知道是否来自IPython,的案例,同时它也适用于cd. 所以

cd <up-arrow><up-arrow> ...

让您快速浏览以前的cd命令。