如何使用 pushd 和 popd 命令?

syn*_*gma 405 shell cd-command pushd

两者的实际用途是什么,pushd以及popd何时使用这两个命令优于cdand cd -

编辑:我正在寻找一些使用这两个命令的实际示例或将堆栈与目录保持在一起的原因(当您有制表符完成、cd -、缩短的别名cd ..等时)。

slm*_*slm 375

pushdpopddirs是 shell 内置函数,允许您操作目录堆栈。这可用于更改目录但返回到您来自的目录。

例如

从以下目录开始:

$ pwd
/home/saml/somedir
$ ls
dir1  dir2  dir3
Run Code Online (Sandbox Code Playgroud)

推送到 dir1

$ pushd dir1
~/somedir/dir1 ~/somedir
$ dirs
~/somedir/dir1 ~/somedir
Run Code Online (Sandbox Code Playgroud)

dirs命令确认我们现在在堆栈上有 2 个目录。dir1和原始目录,somedir注意:我们的“当前”目录是~/somedir/dir1.

推送到 ../dir3 (因为我们现在在里面dir1

$ pushd ../dir3
~/somedir/dir3 ~/somedir/dir1 ~/somedir
$ dirs
~/somedir/dir3 ~/somedir/dir1 ~/somedir
$ pwd
/home/saml/somedir/dir3
Run Code Online (Sandbox Code Playgroud)

dirs显示我们现在堆栈中有 3 个目录。dir3dir1、 和somedir。注意方向。每个新目录都添加到左侧。当我们开始弹出目录时,它们也会来自左侧。

手动将目录更改为 ../dir2

$ cd ../dir2
$ pwd
/home/saml/somedir/dir2
$ dirs
~/somedir/dir2 ~/somedir/dir1 ~/somedir
Run Code Online (Sandbox Code Playgroud)

现在开始弹出目录

$ popd
~/somedir/dir1 ~/somedir
$ pwd
/home/saml/somedir/dir1
Run Code Online (Sandbox Code Playgroud)

注意我们弹回了dir1.

再次弹出...

$ popd
~/somedir    
$ pwd
/home/saml/somedir
Run Code Online (Sandbox Code Playgroud)

我们又回到了开始的地方,somedir

可能会有点混乱,但堆栈的头部是您当前所在的目录。因此,当我们回到 时somedir,即使dirs显示如下:

$ dirs
~/somedir
Run Code Online (Sandbox Code Playgroud)

我们的堆栈实际上是空的。

$ popd
bash: popd: directory stack empty
Run Code Online (Sandbox Code Playgroud)

  • 我经常在脚本 b/c 中使用 `pushd` 和 `popd`,它们使我不必记住我来自哪里,我总是可以只用 `popd` 从我来的地方回来。我通常会执行 `popd >/dev/null 2>&1` 使其静音。我每天在我的 shell 中使用 cd- 。本文中还有其他一些节省时间的技巧:http://www.thegeekstuff.com/2008/10/6-awesome-linux-cd-command-hacks-productivity-tip3-for-geeks/。 (30认同)
  • 谢谢,我完全理解堆栈的概念以及这个命令是如何工作的。但是,我正在寻找一些与目录保持堆栈的实际原因(当您有制表符完成时,`cd -`,缩短`cd ..` 的别名等)。 (29认同)
  • @Garrett @slm 因为 `cd -` 只跟踪最后一个目录,我想如果你调用一个也在内部更改目录的函数,可能会出现问题。在这种情况下,该功能最终会重置 - 到您的当前目录,而不是您想要弹回的目录。pushd/popd 是最安全的方法。注意:我还没有测试我的理论。 (6认同)
  • 为什么不在第一个 `popd` 之后回到 `~/somedir/dir3`? (5认同)
  • @Garrett - 我无法想象。 (2认同)

Jun*_*ami 235

一个非常有用的用例pushdpopd命令可以同时处理多个文件夹。

您可以非常轻松地浏览堆栈,因为它已被枚举。这意味着,您可以在工作期间使用多个工作文件夹。

请参阅下面的简单示例。


首先,让我们创建示例文件夹结构。

    user@vb:~$ mkdir navigate
    user@vb:~/navigate$ mkdir dir1
    user@vb:~/navigate$ mkdir dir2
    user@vb:~/navigate$ mkdir dir3
Run Code Online (Sandbox Code Playgroud)

然后您可以将所有文件夹添加到堆栈中:

    user@vb:~/navigate$ pushd dir1/
    ~/navigate/dir1 ~/navigate
    user@vb:~/navigate/dir1$ pushd ../dir2/
    ~/navigate/dir2 ~/navigate/dir1 ~/navigate
    user@vb:~/navigate/dir2$ pushd ../dir3/
    ~/navigate/dir3 ~/navigate/dir2 ~/navigate/dir1 ~/navigate
Run Code Online (Sandbox Code Playgroud)

您可以通过以下方式查找:

    user@vb:~/navigate/dir3$ dirs -v
     0  ~/navigate/dir3
     1  ~/navigate/dir2
     2  ~/navigate/dir1
     3  ~/navigate
Run Code Online (Sandbox Code Playgroud)

为了安全导航,您需要将最后一个(零)文件夹添加两次,因为它将始终被重写:

    user@vb:~/navigate/dir3$ pushd .
    user@vb:~/navigate/dir3$ dirs -v
     0  ~/navigate/dir3
     1  ~/navigate/dir3
     2  ~/navigate/dir2
     3  ~/navigate/dir1
     4  ~/navigate
Run Code Online (Sandbox Code Playgroud)

现在,您可以跳过这些文件夹并使用堆栈作为文件夹的别名。我想以下部分是不言自明的:

    user@vb:~/navigate/dir3$ cd ~4
    user@vb:~/navigate$ dirs -v
     0  ~/navigate
     1  ~/navigate/dir3
     2  ~/navigate/dir2
     3  ~/navigate/dir1
     4  ~/navigate
    user@vb:~/navigate$ cd ~3
    user@vb:~/navigate/dir1$ dirs -v
     0  ~/navigate/dir1
     1  ~/navigate/dir3
     2  ~/navigate/dir2
     3  ~/navigate/dir1
     4  ~/navigate
    user@vb:~/navigate/dir1$ touch text.txt
    user@vb:~/navigate/dir1$ cp text.txt ~2
    user@vb:~/navigate/dir1$ ls ~2
    text.txt
    user@vb:~/navigate/dir1$ dirs -v
     0  ~/navigate/dir1
     1  ~/navigate/dir3
     2  ~/navigate/dir2
     3  ~/navigate/dir1
     4  ~/navigate
Run Code Online (Sandbox Code Playgroud)

额外的提示是为dirs -v.

例如:

# In ~/.bashrc
alias dirs="dirs -v"
Run Code Online (Sandbox Code Playgroud)

  • 你可以通过```dirs -c```清除堆栈 (38认同)
  • +1 实际上给出了一些实际例子。从手册页很容易看出 pushd/popd 做了什么,但是 dirs 和 cd ~# 一开始并不明显。 (28认同)
  • @Jun,有“mkdir dir{1,2,3}”可以一次性创建 3 个目录。 (2认同)

Pet*_*ica 51

使用 dirs 堆栈的一个简单用例是您无法仅通过 cd 执行的操作:

pushd .将当前目录 XX 添加到dirs堆栈。之后,您可以使用cd, 并返回 XX ,popd无论您在目录树中有多“远”(可以跳过多个级别,横向等),您都可以这样做。在 bash 脚本中特别有用。

  • 我认为这是我最常利用的功能。因为`pushd`/`popd` 独立于`cd` 工作,你可以将它们用作比`cd -` 更稳定的书签。 (6认同)
  • 这是与 cd -, IMO 进行比较的唯一实质性答案。至于是否pushd foo;<随机目录改变>; popd 比 a=foo 更有价值;cd $a; <随机目录改变>; cd $a ... 对于脚本,我可以看到前者(pushd)在语法上的便利性,但后者([显式] 变量!)在清晰度方面有了巨大的改进。对于交互式会话,我想我首先假设我的目录层次结构正确组织,如果我迷路了,只需 cd ~/back/to/obvious/path。 (6认同)
  • @HarendraSingh 你碰巧没有设置“AUTO_PUSHD”?它会让 `cd` 表现得像 `pushd`,取消设置它,你就会回到“正常行为”。 (3认同)
  • 哦,那是因为使用 zsh,当我更改为 bash 时,它工作正常 (2认同)

unx*_*nut 14

pushdpopd允许您操作堆栈上的目录。

当你创建pushd一个目录时,你将当前目录放在堆栈上并将目录更改为指定为参数的目录。

popd 将允许您返回堆栈上的目录。

如果重复,目录遍历将被保留,您可以按照与保存目录相反的顺序返回保存的目录。


eli*_*eli 13

对于bash,基本上:而不是使用 cd 可以pushd用来更改目录。实际使用:保存访问目录的历史记录(正确:堆叠)并且可以在它们之间切换:

pushd /home; pushd /var; pushd log
Run Code Online (Sandbox Code Playgroud)

要查看堆栈使用情况dirs并更轻松地导航(要获取“堆栈条目”的编号,请使用:

dirs -v
Run Code Online (Sandbox Code Playgroud)

输出:

me@myhost:/home$ dirs -v
 0  /home
 1  /var
 2  /tmp
Run Code Online (Sandbox Code Playgroud)

现在使用这些数字cd~喜欢:

cd ~1
Run Code Online (Sandbox Code Playgroud)

但是这些数字现在重新排列,位置“0”会改变,所以只需pushd将目录放在顶部位置两次(或在位置 0 上使用虚拟),例如:

me@myhost:/home$ dirs -v
 0  /home
 1  /home
 2  /var
 3  /tmp
Run Code Online (Sandbox Code Playgroud)

现在 1..3 将保持他们的位置

(要从堆栈中释放当前目录/从历史记录中删除它,请使用popd


Mer*_*ury 9

pushd/popd 是一个如此简单的概念,我花了一些时间来理解,因为人们倾向于通过将这些命令定义为“操作目录堆栈”的命令来教授它,在我看来,这非常令人困惑。

我以不同的方式看待它:

pushd [folder_name] - 将 cd 到 [folder_name] 并将在目录堆栈中记录目标 [folder_name],而堆栈中的顶级目录将始终是您所在的当前目录

popd - 首先将您 cd 到堆栈顶部的目录记录,然后删除文档(从目录堆栈中删除它)

dirs - 将打印 dir 堆栈(可以视为 dir Db,其中最左边的条目是当前目录(堆栈顶部)

因此,两个最流行的用例是:

用例 1:使用 pushd 和 popd 导航

root@mypc:/main/$ ls
dir1  dir2  dir3  dir4

root@mypc:/main/$ dirs   # prints the current stack
/main

root@mypc:/main/$ pushd dir1    # Will cd to dir1 and document dir1 in dir stack, stack is now:
/main/dir1 /main 
root@mypc:/main/dir1$    # I am now in /main/dir1

root@mypc:/main/dir1$    # Now let's go wild and document whatever I want
root@mypc:/main/dir1$ pushd ../dir2 
root@mypc:/main/dir2$     # Woo I am in /main/dir2
root@mypc:/main/dir2$ pushd ../dir3 
root@mypc:/main/dir3$     # Woo I am in /main/dir3
root@mypc:/main/dir3$ pushd ../dir4 
root@mypc:/main/dir4$     # Woo I am in /main/dir4
root@mypc:/main/dir4$ dirs   # Now dir stack is:
/main/dir4 /main/dir3 /main/dir2 /main/dir1 /main
Run Code Online (Sandbox Code Playgroud)

假设我执行了上述操作,因为我想导航回我记录的那些文件夹!

请注意,如果我手动 cd,我会影响顶部目录堆栈条目(始终是当前目录)

root@mypc:/main/dir4$ cd ..   # Now dir stack is:
# (note that /main appear in the leftmost as well which is the top of the stack)
/main /main/dir3 /main/dir2 /main/dir1 /main
root@mypc:/main$ 
Run Code Online (Sandbox Code Playgroud)

现在让我们向后导航:

root@mypc:/main$ popd
root@mypc:/main$     # Still in /main since it was at the top of the dir stack
root@mypc:/main$ dirs    # Stack is now:
/main/dir3 /main/dir2 /main/dir1 /main

root@mypc:/main$ popd
root@mypc:/main/dir3$ popd    # Woo in dir3 now, about to navigate to dir2
root@mypc:/main/dir2$ popd    # Woo in dir2, about to navigate to dir1
root@mypc:/main/dir1$ dirs    # Stack is now:
/main
Run Code Online (Sandbox Code Playgroud)

同样,我可以记录我想要的任何目录,然后手动导航到另一个目录,然后我将能够轻松返回到我插入到堆栈中的记录目录。

用例 2:使用数字堆栈索引导航

假设我使用 pushd dir4 dir3 dir2 dir1 推送,现在运行 dir -v 将显示:

root@mypc:/main$ dirs -v
 0  /main/dir1  (this is the current dir you are in always)
 1  /main/dir2
 2  /main/dir3
 3  /main/dir4
Run Code Online (Sandbox Code Playgroud)

现在您可以使用堆栈索引执行任何涉及目录的 Linux 操作:

root@mypc:/main$ cp ~2/temp.txt ~3/new_temp.txt    # this will run in the background, something like:
# cp /main/dir2/temp.txt  /main/dir3/new_temp.txt
Run Code Online (Sandbox Code Playgroud)

您甚至可以从目录堆栈中删除特定条目:

root@mypc:/main$ popd ~4
Run Code Online (Sandbox Code Playgroud)

希望使用“记录”一词或将 dir 堆栈视为某种 Db 可以简化概念!


小智 5

我发现使用 dirs/popd/pushd 有点不舒服。我在 tcsh 中提出了我的个人解决方案,方法是将以下代码添加到 .alias 中

  foreach b (. , - 0 1 2 3 4 5 6 7 8 9 )
    alias p$b       'set a=`pwd`; echo $a >! ~/.mydir'$b
    alias cd$b      'cd "`cat ~/.mydir'$b'`"'
    alias del$b     'rm -v ~/.mydir'$b
    alias home$b    'set a="~"; echo $a >! ~/.mydir'$b
  end
    alias cdl       'grep / ~/.mydir*'
Run Code Online (Sandbox Code Playgroud)

例如,我以这种方式别名“p”。将当前工作目录保存到文件 ~/.mydir 中。和“光盘”。随时随地恢复该目录。“德尔。” 删除相应的文件;“家。” 将目录设置为主目录(相当于 cd; p. );“cdl”列出了保存的目录。请注意,如果您使用 ~/Dropbox/.mydir$b(或任何其他云服务,例如 ownCloud)而不是 ~/.mydir$b,您将获得一种跨不同帐户和机器使用首选目录的智能方法。


eli*_*lig 5

简而言之——当您需要在 2 个以上的目录之间导航时,通常会来回多次,因为cd -不会用超过 2 个文件夹的任何内容来剪切它。

因此,例如,不要通过查看缓冲区的历史记录或选项卡完成长路径来尝试重新提出以前的长路径,您只需将重要路径堆叠起来,如果需要,您可以方便地仅通过它们的编号移动到它们。在复杂的目录结构和长路径之间旋转变得流畅而迅速。

内置程序还允许您重新排序堆栈或弹出您不再需要的目录,从而使您的工作流程具有灵活性。

目录堆叠也可以类似地在脚本中用于跨越多个目录的操作。


jsk*_*och 5

使用cdcd -允许您仅在两个最近使用的目录之间切换。您的“目录工作集”大小是二。

使用pushd,您可以在工作集中保留任意数量的目录。

pushd大部分时间都使用而不是cd. 一旦您使用 建立了一堆活动目录pushd directory_name,您就可以使用 整天在它们之间跳转pushd ~#

pushd dir1
pushd ../dir2
pushd /full/path/to/dir3

# There are now three directories in the stack.

pushd ~3
pushd ~2

# The same three directories are still on the stack, 
# just in a different order.
Run Code Online (Sandbox Code Playgroud)

popd很少使用,只有当我知道我已经使用完该目录并想从堆栈中删除该目录时才使用。

转到目录并将其从堆栈中删除:

popd ~2
Run Code Online (Sandbox Code Playgroud)

保留在当前目录中并从堆栈中删除另一个目录:

popd +2
Run Code Online (Sandbox Code Playgroud)

您最终得到的工作方式类似于打开多个终端窗口或选项卡(每个目录对应一个您正在工作的目录),但全部都在一个终端中。这可以节省屏幕空间,此外,由于目录路径都在一个 shell 中可用,因此您可以执行以下操作:

  • 在当前正在使用的目录之间复制文件
  • 查看或编辑另一个目录中的文件而无需前往那里

例子:

cp ~2/myfile.txt ~4
less ~2/myfile.txt
Run Code Online (Sandbox Code Playgroud)

tcsh(但不是bash)中,您甚至可以将目录堆栈保存到文件中并在以后恢复。

节省:

dirs -S ~/dirstack
Run Code Online (Sandbox Code Playgroud)

恢复:

dirs -L ~/dirstack
Run Code Online (Sandbox Code Playgroud)

否则,只需将示例~中的内容替换bash=for use in tcsh

pushd =2
popd =4
popd +1
Run Code Online (Sandbox Code Playgroud)