如何使用推入和弹出命令?


332

什么都的实际应用,pushdpopd时有过使用这两个命令的优势cdcd -

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

Answers:


304

pushdpopddirs是shell内置程序,可让您操纵目录堆栈。这可以用于更改目录,但可以返回到您来自的目录。

例如

从以下目录启动:

$ ls
dir1  dir2  dir3

推到dir1

$ pushd dir1
~/somedir/dir1 ~/somedir
$ dirs
~/somedir/dir1 ~/somedir

dirs命令确认我们现在在堆栈上有2个目录。dir1和原始目录somedir

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

$ pushd ../dir3
~/somedir/dir3 ~/somedir/dir1 ~/somedir
$ dirs
~/somedir/dir3 ~/somedir/dir1 ~/somedir
$ pwd
/home/saml/somedir/dir3

dirs显示我们现在在堆栈中有3个目录。dir3dir1somedir。注意方向。每个新目录都添加到左侧。当我们开始弹出目录时,它们也将从左侧出现。

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

$ cd ../dir2
$ pwd
/home/saml/somedir/dir2
$ dirs
~/somedir/dir2 ~/somedir/dir1 ~/somedir

现在开始弹出目录

$ popd
~/somedir/dir1 ~/somedir
$ pwd
/home/saml/somedir/dir1

请注意,我们跳回到dir1

再次弹出...

$ popd
~/somedir    
$ pwd
/home/saml/somedir

我们回到了起点somedir

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

$ dirs
~/somedir

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

$ popd
bash: popd: directory stack empty

19
谢谢,我完全理解堆栈的概念以及该命令的工作方式。但是,我正在寻找一些与目录保持堆栈的实际原因(当您具有制表符补全,,cd -用于缩短的别名cd ..等时)。
结构体

21
我经常在脚本b / c中使用pushdpopd,它们使我不必记住我来自哪里,我总是可以仅仅popd从我那里回来。我通常会popd >/dev/null 2>&1使其保持沉默。我每天在外壳中使用cd-。本文中还有一些其他节省时间的技巧:thegeekstuff.com/2008/10/…
slm

2
@Garrett-我无法想象的。
slm

4
@Garrett @slm因为cd -只跟踪最后一个目录,所以我想如果调用一个也在内部更改目录的函数,可能会出现问题。在这种情况下,该函数最终将重置-您的当前目录,而不是您要弹出的目录。推入/弹出是最安全的方法。注意:我尚未检验我的理论。
Binary Phile 2014年

5
为什么不回到~/somedir/dir3第一个之后popd呢?
ziyuang '16

198

一个真正有用的使用情况pushdpopd命令的同时与几个文件夹的工作。

由于已枚举,因此您可以非常轻松地浏览堆栈。意思是,在工作期间您可以使用多个工作文件夹。

请参阅下面的简单示例。


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

    user@vb:~$ mkdir navigate
    user@vb:~/navigate$ mkdir dir1
    user@vb:~/navigate$ mkdir dir2
    user@vb:~/navigate$ mkdir dir3

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

    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

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

    user@vb:~/navigate/dir3$ dirs -v
     0  ~/navigate/dir3
     1  ~/navigate/dir2
     2  ~/navigate/dir1
     3  ~/navigate

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

    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

现在,您可以在这些文件夹中跳转,并像使用文件夹别名一样使用堆栈。我想以下部分是自我解释:

    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

另一个提示是为创建别名dirs -v

例如:

# In ~/.bashrc
alias dirs="dirs -v"

28
您可以在dirs -c
Jun Murakami

19
+1实际给出一些实际例子。从手册页可以很容易地看到push / popd的功能,但是起初,dirs和cd〜#并不明显。
Scribblemacher

您也可以使用fasd之类的解决方案来代替这种工作流程,不过
WuTheFWasThat

因此,对于更短暂的使用案例,它比设置CDPATH更好?
rfabbri '16

2
@Jun,有一个“ mkdir dir {1,2,3}”,可以一口气创建3个目录。
Bulat M.

39

使用dirs堆栈的一个简单用例是仅cd无法实现的功能:

pushd .将当前目录XX添加到dirs堆栈。之后,您可以使用cd来回移动,然后返回XX即可,popd无论您在目录树中有多远(可以跳过多个级别,横向等等)。在bash脚本中尤其有用。


2
我认为这是我最常使用的功能。由于pushd/ popd工作独立于cd,因此您可以将它们用作比cd -
Gordon Bean

对我来说,这不是真的。每次我使用cd时,我的堆栈都会更改。
Harendra Singh

哦,那是使用zsh的原因,当我换成bash时,它可以正常工作
Harendra Singh

4
这是与cd-IMO进行比较的唯一实质性答案。至于是否推了foo;<更改随机目录>; popd比a = foo更有价值;cd $ a; <更改随机目录>; cd $ a ...对于脚本,我可以看到前者(推送)在语法上有一点点方便,但是后者([显式]变量!)的清晰度有了很大提高。对于交互式会话,我想我只是假设我的目录层次结构首先是正确组织的,如果我迷路了,则只需使用cd〜/ back / to / obvious / path。
Jan Kyu Peblik

9

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

当你pushd的目录,你把当前目录堆栈并更改目录指定为一个参数之一。

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

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


6

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

pushd /home; pushd /var; pushd log

要查看堆栈的使用dirs并简化导航(获取“堆栈条目”的编号,请使用:

dirs -v

输出:

me@myhost:/home$ dirs -v
 0  /home
 1  /var
 2  /tmp

现在将这些数字与cd和一起使用~

cd ~1

但是现在这些数字已重新排列,位置“ 0”将更改,因此只需pushd两次将目录移到顶部位置(或在位置0上使用虚拟对象),例如:

me@myhost:/home$ dirs -v
 0  /home
 1  /home
 2  /var
 3  /tmp

现在1..3将保持位置

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


5

我发现的一种实际用途是使用push和popd在目录之间切换。

假设我们有两个目录dir1和dir2,由于某些xyz原因,我需要在两个目录之间连续切换。

目前我在somedir中,它有两个目录dir1dir2

alcohol@alcohol-machine:~/somedir$ ls
dir1  dir2
alcohol@alcohol-machine:~/somedir$ 

现在我切换到 dir1

alcohol@alcohol-machine:~/somedir$ cd dir1
alcohol@alcohol-machine:~/somedir/dir1$ pwd
/home/alcohol/somedir/dir1

现在我将添加dir1到堆栈并切换到dir2

alcohol@alcohol-machine:~/somedir/dir1$ pushd /home/alcohol/somedir/dir2
~/somedir/dir2 ~/somedir/dir1
alcohol@alcohol-machine:~/somedir/dir2$

如您所见,我现在拥有dir2dir1在堆栈中,目前进入dir2

现在切换回去dir1,我将运行pushd || popd

alcohol@alcohol-machine:~/somedir/dir2$ pushd || popd
~/somedir/dir1 ~/somedir/dir2
alcohol@alcohol-machine:~/somedir/dir1$ 

瞧,我进入dir1,并且在堆栈上有dir1和dir2。要再次切换回dir2,请运行pushd || popd

alcohol@alcohol-machine:~/somedir/dir2$ pushd || popd
~/somedir/dir1 ~/somedir/dir2
alcohol@alcohol-machine:~/somedir/dir1$ 

这是在目录之间切换的简单方法。现在,您可能会知道,为什么我需要在目录之间切换?好一个用例是,当我处理Web应用程序时,我的make文件位于一个目录中,而日志文件位于另一个目录中。通常在调试应用程序时,我需要在日志目录之间切换,以检查最新日志,然后切换回make目录,进行一些更改并构建应用程序。


11
(1)问题问,“ pushdpopd过去相比有什么优势cd -?” 您正在确切描述做什么,您显然没有回答该问题cd -。(2)说的重点是什么pushd || popd?是的,我知道这cmdA || cmdB意味着运行cmdA,如果运行失败,则运行cmdB。我想问一下在这种情况下有什么好处。  pushd不带参数的意思是“交换目录堆栈中的前两个元素”;如果当前目录是目录堆栈中的唯一元素,则失败。在这种情况下,popd也会失败。
G-Man

3
我不敢相信没有人支持您!救命!真是太棒了。谢谢。我认为,切换和用例。pushdpopd
桑尼,2015年

3
pushd || popd在目录之间进行切换相比,有两种截然不同的方式要求键入的内容少得多:pushd不带参数就可以做到这一点。cd -明确存在的唯一目的是切换回上一个目录。另外,该问题要求pushdover 的优点cd -,而该答案显然没有任何缺点,只有缺点:多打字。
本杰明·里格斯

在bash中,不带参数的push交换了前两个目录并返回0。为什么需要|| popd切换?请解释。(这还不够吗?)
Johnny Wong

@Sonny只需用于cd -在两个目录之间切换。此外cd,不带任何参数将返回到您的主目录。
史蒂夫(Steve)

2

简而言之-当您需要在2个以上的目录之间导航时,通常来回往返几次,因为cd -不会用2个以上的文件夹来剪切它。

因此,例如,与其通过查看缓冲区的历史记录来尝试重新找到先前的长路径,也不用制表符完成一条长路径,您只需将重要的那些堆积起来,并在需要时方便地仅按其编号移动它们。在复杂的目录结构和长路径之间旋转变得流畅而迅速。

内建函数还允许您重新排序堆栈或弹出不再需要的目录,从而使工作流程更加灵活。

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


1

我发现使用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*'

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


0

我在我的bash_profile和.bashrc中像这样使用它

vi .bash_profile
alias dirs="dirs -v"
source d.sh
:wq

vi .bashrc
alias dirs="dirs -v"
:wq

vi d.sh
pushd ~/Documents/GIT/seiso-data
pushd ~/Documents/GIT/ewe/EosRegistry
pushd ~/Documents/GIT_LODGING/site-cookbooks
pushd ~/Documents/CHEF_LODGING
pushd  .
:wq

它可以帮助我在目录之间跳转到终端上最新使用的目录。:-)希望它可以帮助您使用push而不是popd我使用cd〜stackednumber


0

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

使用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.

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

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

popd ~2

停留在当前目录中,然后从堆栈中删除另一个目录:

popd +2

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

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

例子:

cp ~2/myfile.txt ~4
less ~2/myfile.txt

tcsh(但不是bash)中,您甚至可以将目录堆栈保存到文件中,然后再将其还原。

救:

dirs -S ~/dirstack

恢复:

dirs -L ~/dirstack

否则,只需更换~bash用例=中使用tcsh

pushd =2
popd =4
popd +1

0

push / popd是一个简单的概念,使我花了一段时间才能理解,因为人们倾向于通过将这些命令定义为“操纵目录栈”的命令来教它,我认为这令人困惑。

我以不同的方式看待它:

推入[folder_name] -将cd到[folder_name],并在目录堆栈中记录目标位置[folder_name],而堆栈中的顶层目录始终是您所在的当前目录

popd-首先将您cd到堆栈顶部的目录记录中,然后将其从堆栈中删除

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

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

用例1:使用推入式和弹出式导航

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

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

请注意,如果我手动进行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$ 

让我们现在向后导航:

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

同样,我可以记录所需的任何目录,然后手动导航至另一个目录,这样我就可以轻松返回到我插入堆栈的记录目录。

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

可以说我使用push 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

现在,您可以使用堆栈索引执行任何涉及目录的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

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

root@mypc:/main$ popd ~4

希望使用“记录”一词或将目录堆栈作为某种Db来简化概念!

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.