在多个目录之间进行系统管理的快速命令行方法是什么?我的意思是,我可以使用pushd .
和popd
进行切换,但是如果我想存储倍数并在它们之间循环,而不是将它们从堆栈底部永久弹出,该怎么办?
cd -
从这个问题开始搜寻后才得知的。
cd
手工无处不在。很痛苦。但是,使用带有Tab键的自动完成功能。
在多个目录之间进行系统管理的快速命令行方法是什么?我的意思是,我可以使用pushd .
和popd
进行切换,但是如果我想存储倍数并在它们之间循环,而不是将它们从堆栈底部永久弹出,该怎么办?
cd -
从这个问题开始搜寻后才得知的。
cd
手工无处不在。很痛苦。但是,使用带有Tab键的自动完成功能。
Answers:
使用pushd
在目录栈,然后在目录中的特殊的名字:~1
,~2
,等。
例:
tmp $ dirs -v
0 /tmp
1 /tmp/scripts
2 /tmp/photos
3 /tmp/music
4 /tmp/pictures
tmp $ cd ~3
music $ dirs -v
0 /tmp/music
1 /tmp/scripts
2 /tmp/photos
3 /tmp/music
4 /tmp/pictures
music $ cd ~2
photos $ cd ~4
pictures $ cd ~3
music $ cd ~1
scripts $
pushd
以这种方式使用的最有效方法是加载目录列表,然后再添加一个目录作为当前目录,然后可以在静态编号之间跳转而不影响目录在堆栈中的位置。
另外值得一提的是,cd -
将带你到你在最后一个目录。 所以会cd ~-
。
的优势,~-
经过短短-
的是,-
特定于cd
,而~-
扩大你的shell以同样的方式~1
,~2
等都是。在非常长的目录路径之间复制文件时,这非常方便。例如:
cd /very/long/path/to/some/directory/
cd /another/long/path/to/where/the/source/file/is/
cp myfile ~-
以上等同于:
cp /another/long/path/to/where/the/source/file/is/myfile /very/long/path/to/some/directory/
cd -
cd -
就像Forth一样DROP DUP
,例如,如果从目录a开始,堆栈为abcd,则a cd -
将堆栈更改为bbcd。bash
但是,也许这是一个错误,因为一秒钟cd -
将堆栈更改回abcd。由此可以推断,cd -
除了更改堆栈之外,还使用一些单独的数据结构来存储先前的目录。
cd -
用途$OLDPWD
,仅此而已。
cd -
是较早的bash功能,后来又添加了一个堆栈,但是担心破坏旧代码比他们想要更简单的设计更多。对上一个的更正,其cd -
行为类似于Forth OLDPWD @ SWAP OLDPWD ! DUP .
Different cd foo
,显示cd -
已交换目录的名称。
bash
pushd
使用+
和内置的-
可以旋转目录堆栈。语法可能有些混乱,可能是因为该堆栈是从零开始的数组。这些简单的包装函数在目录堆栈中循环:
# cd to next directory in stack (left rotate)
ncd(){ pushd +1 > /dev/null ; }
# cd to previous directory in stack (right rotate)
pcd(){ pushd -0 > /dev/null ; }
测试:设置四个目录的堆栈。
dirs -c # clear directory stack
cd /home ; pushd /etc ; pushd /bin ; pushd /tmp
现在/ tmp是当前目录,并且堆栈如下所示:
/tmp /bin /etc /home
切换到堆栈中的下一个目录(并显示),四次:
ncd ; pwd ; ncd ; pwd ; ncd ; pwd ; ncd ; pwd
输出:
/bin
/etc
/home
/tmp
切换到堆栈中的上一个目录(并显示它)四次:
pcd ; pwd ; pcd ; pwd ; pcd ; pwd ; pcd ; pwd
输出:
/home
/etc
/bin
/tmp
注释cd -
:通配符的答案有助于说明如何cd -
不使用$ DIRSTACK数组(它使用$ OLDPW变量),因此cd -
不会像基于堆栈的交换那样影响$ DIRSTACK。为了解决这个问题,这是一个基于$ DIRSTACK的简单交换函数:
scd() { { pushd ${DIRSTACK[1]} ; popd -n +2 ; } > /dev/null ; }
测试:
dirs -c; cd /tmp; \
pushd /bin; \
pushd /etc; \
pushd /lib; \
pushd /home; \
scd; dirs; scd; dirs
输出:
/bin /tmp
/etc /bin /tmp
/lib /etc /bin /tmp
/home /lib /etc /bin /tmp
/lib /home /etc /bin /tmp
/home /lib /etc /bin /tmp
popd
,在不更改目录的情况下将其删除,请执行popd -n
。要清除堆栈呢dirs -c
。不幸的是,bash设计人员将这种有用的功能隐藏在非直观的语法中。参见man bash
下pushd
,dirs
等
我写了一个脚本xyzzy
来做到这一点:
#!/bin/bash
i="$1"
i=$((${i//[^0-9]/}))
i="$(($i-1+0))"
b="$2"
b=$((${b//[^0-9]/}))
b="$(($b-1+0))"
if [ -z "$XYZZY_INDEX" ]; then
XYZZY_INDEX="$((-1))"
fi
if [ ! -f "/tmp/xyzzy.list" ]; then
touch /tmp/xyzzy.list
chmod a+rw /tmp/xyzzy.list
fi
readarray -t MYLIST < /tmp/xyzzy.list
showHelp(){
read -r -d '' MYHELP <<'EOB'
xyzzy 1.0
A command for manipulating escape routes from grues. Otherwise known as a useful system admin
tool for storing current directories and cycling through them rapidly. You'll wonder why this
wasn't created many moons ago.
Usage: xyzzy [options]
help/-h/--help Show the help.
this/-t/--this Store the current directory in /tmp/xyzzy.list
begone/-b/--begone Clear the /tmp/xyzzy.list file. However, succeed with a number and
it clears just that item from the stored list.
show/-s/--show Show the list of stored directories from /tmp/xyzzy.list
. # Use a number to 'cd' to that directory item in the stored list. This syntax is odd:
. xyzzy 2
...would change to the second directory in the list
. [no options] Use the command alone and it cd cycles through the next item in the stored
list, repeating to the top when it gets to the bottom. The dot and space before xyzzy
is required in order for the command to run in the current shell and not a subshell:
. xyzzy
Note that you can avoid the odd dot syntax by adding this to your ~/.bashrc file:
alias xyzzy=". xyzzy"
and then you can do "xyzzy" to cycle through directories, or "xyzzy {number}" to go to a
specific one.
May you never encounter another grue.
Copyright (c) 2016, Mike McKee <https://github.com/volomike>
EOB
echo -e "$MYHELP\n"
}
storeThis(){
echo -e "With a stroke of your wand, you magically created the new escape route: $PWD"
echo "$PWD" >> /tmp/xyzzy.list
chmod a+rw /tmp/xyzzy.list
}
begoneList(){
if [[ "$b" == "-1" ]]; then
echo "POOF! Your escape routes are gone. We bless your soul from the ever-present grues!"
>/tmp/xyzzy.list
chmod a+rw /tmp/xyzzy.list
else
echo -n "Waving your wand in the dark, you successfully manage to remove one of your escape routes: "
echo "${MYLIST[${b}]}"
>/tmp/xyzzy.list
chmod a+rw /tmp/xyzzy.list
for x in "${MYLIST[@]}"; do
if [[ ! "$x" == "${MYLIST[${b}]}" ]]; then
echo "$x" >> /tmp/xyzzy.list
fi
done
fi
}
showList(){
echo -e "These are your escape routes:\n"
cat /tmp/xyzzy.list
}
cycleNext(){
MAXLINES=${#MYLIST[@]}
XYZZY_INDEX=$((XYZZY_INDEX+1))
if [[ $XYZZY_INDEX > $(($MAXLINES - 1)) ]]; then
XYZZY_INDEX=0
fi
MYLINE="${MYLIST[${XYZZY_INDEX}]}"
cd "$MYLINE";
}
switchDir(){
MYLINE="${MYLIST[${i}]}"
cd "$MYLINE";
}
if [[ "$@" == "" ]];
then
cycleNext
fi;
while [[ "$@" > 0 ]]; do case $1 in
help) showHelp;;
--help) showHelp;;
-h) showHelp;;
show) showList;;
-s) showList;;
--show) showList;;
list) showList;;
this) storeThis;;
--this) storeThis;;
-t) storeThis;;
begone) begoneList;;
--begone) begoneList;;
*) switchDir;;
esac; shift
done
export XYZZY_INDEX
我使用它的方式是先复制到/usr/bin
文件夹,然后chmod a+x
在其上。然后,我编辑我的root和用户帐户~/.bashrc
文件以在底部包括以下几行:
alias xyzzy='. xyzzy'
alias xy='. xyzzy'
“ xy”是命令的缩写形式,可加快键入速度。
然后,我可以使用以下命令将当前目录存储在列表中:
xyzzy this
...并根据需要重复。当我用所需的目录填充此列表后,它们将保留在该目录中,直到我重新启动计算机为止,因为那是再次清除/ tmp的时候。然后我可以输入...
xyzzy show
...列出当前保存的目录。为了切换到目录,我有两种选择。一种选择是按索引指定路径(它是从1开始的索引),如下所示:
xyzzy 2
...将切换到列表中第二个目录。或者,我可以不使用索引号,而是这样做:
xyzzy
...让它根据需要遍历每个目录。要执行更多命令,请键入:
xyzzy help
当然,我添加的愚蠢的echo语句使工作更加有趣。
请注意,xyzzy是对Collosal Cave文字冒险的引用,在其中键入xyzzy可以让您在游戏中的两个房间之间切换,以避免产生毛刺。
我使用了一个名为z [link]的小脚本,即使它不能完全满足您的要求,也可能会引起您的兴趣。
NAME
z - jump around
SYNOPSIS
z [-chlrtx] [regex1 regex2 ... regexn]
AVAILABILITY
bash, zsh
DESCRIPTION
Tracks your most used directories, based on 'frecency'.
After a short learning phase, z will take you to the most 'frecent'
directory that matches ALL of the regexes given on the command line, in
order.
For example, z foo bar would match /foo/bar but not /bar/foo.
也有cd_func
Petar Marinov的书,基本上cd
有多达10个条目的历史记录:http : //linuxgazette.net/109/misc/marinov/acd_func.html
# do ". acd_func.sh"
# acd_func 1.0.5, 10-nov-2004
# petar marinov, http:/geocities.com/h2428, this is public domain
cd_func ()
{
local x2 the_new_dir adir index
local -i cnt
if [[ $1 == "--" ]]; then
dirs -v
return 0
fi
the_new_dir=$1
[[ -z $1 ]] && the_new_dir=$HOME
if [[ ${the_new_dir:0:1} == '-' ]]; then
#
# Extract dir N from dirs
index=${the_new_dir:1}
[[ -z $index ]] && index=1
adir=$(dirs +$index)
[[ -z $adir ]] && return 1
the_new_dir=$adir
fi
#
# '~' has to be substituted by ${HOME}
[[ ${the_new_dir:0:1} == '~' ]] && the_new_dir="${HOME}${the_new_dir:1}"
#
# Now change to the new dir and add to the top of the stack
pushd "${the_new_dir}" > /dev/null
[[ $? -ne 0 ]] && return 1
the_new_dir=$(pwd)
#
# Trim down everything beyond 11th entry
popd -n +11 2>/dev/null 1>/dev/null
#
# Remove any other occurence of this dir, skipping the top of the stack
for ((cnt=1; cnt <= 10; cnt++)); do
x2=$(dirs +${cnt} 2>/dev/null)
[[ $? -ne 0 ]] && return 0
[[ ${x2:0:1} == '~' ]] && x2="${HOME}${x2:1}"
if [[ "${x2}" == "${the_new_dir}" ]]; then
popd -n +$cnt 2>/dev/null 1>/dev/null
cnt=cnt-1
fi
done
return 0
}
alias cd=cd_func
if [[ $BASH_VERSION > "2.05a" ]]; then
# ctrl+w shows the menu
bind -x "\"\C-w\":cd_func -- ;"
fi
Siimply使用cd --
,以显示过去的清单给你10个目录cd
艾德和cd -N
(这里N
是入门的指数)去那里。
我主要使用带有oh-my-zsh配置文件的ZSH 。您可以在终端中输入以下匹配项:
# cd /ho
然后,您可以简单地使用箭头(向上和向下)浏览所有shell历史记录,其中仅显示以上述字符开头的条目。因此,例如,如果您转到/home/morfik/Desktop/
和/home/morfik/something/
,则可以非常快速地在目录之间切换。在外壳程序历史记录中有多少个条目都没有关系,但是如果有很多条目,只需使用更好的表达式即可,例如cd /home/morf
,在这里按键盘上的上/下箭头。
还有另一种方法可以实现该解决方案。在这种情况下,您必须使用tmux和FZF。然后,您只需要创建一个热键,例如ctrl-r,然后按它,您的当前窗口将被分割,您将看到以下内容:
现在,您可以使用表达式搜索列表。我刚刚输入^cd /media
,它仅返回以短语开头的条目。当然,您可以键入'cd 'home
以匹配命令以及整个目录名(而不是路径,仅是名称):
~/.bashrc
(或同等的)别名中使用一堆别名来实现此目的。主要目标是接近最小的键入(例如,d5
跳转到池中的目录号5)以在池中的目录之间切换。另外,我们还想使向池中添加目录或从池中删除目录变得容易:
alias pd=pushd
alias po=popd
alias d='dirs -v'
alias d0=d
alias d1='pd +1'
alias d2='pd +2'
alias d3='pd +3'
alias d4='pd +4'
alias d5='pd +5'
alias d6='pd +6'
alias d7='pd +7'
alias d8='pd +8'
alias d9='pd +9'
alias d10='pd +10'
# -- feel free to add more aliases if your typical dir pool is larger than 10
现在,每次将目录压入堆栈时,目录都会添加到编号池0的位置(当前目录),您只需很少键入(d<N>
)就可以跳转(切换目录),并且可以在任何位置查看编号的当前池只需输入时间即可d
。
使用这些别名的一些示例:
$ d
0 /tmp
1 /
2 /usr
d<N>
$ d2
$ pwd
/usr
$ pd /var/log
$ d
0 /var/log
1 /usr
2 /tmp
3 /
$ d3
$ pwd
/
$ d3
$ pwd
/tmp
$ d
0 /tmp
1 /
2 /var/log
3 /usr
$ po
$ d
0 /
1 /var/log
2 /usr
如果安装了iselect,则可以执行以下操作:
$ alias dirselect='cd $(iselect -a $(dirs -l -p | sort -u))'
$ dirselect
这将为您提供基于ncurses的全屏交互式箭头键可导航菜单,以选择要访问的目录cd
。
如果您没有pushd
在当前的shell会话中使用过,则菜单中的目录列表仅以一个条目(当前目录)开始。如果只有一个条目,则该dirselect
别名将仅cd
在没有菜单屏幕的情况下使用,因此它实际上不执行任何操作(除非阻止cd -
执行任何有用的操作)
要将新目录添加到列表中,请使用pushd dir
(或pushd -n dir
在不添加cd
-ing的情况下添加目录)
您可以pushd
通过在.bashrc
或中执行以下操作来预填充堆栈~/.bash_profile
:
for d in /var/tmp /tmp /path/to/somewhere/interesting ; do
pushd -n "$d" > /dev/null
done
您可以使用popd
或删除条目popd -n
。
有关更多信息,请参见help pushd
,help popd
以及help dirs
bash中的。并且,当然man iselect
。
BTW,iselect
可能已为您的发行版预先打包。它适用于Debian和Ubuntu等,也可能适用于其他人。
如果您有5或10个目录,则使用很多,而不必关心最近使用的 5或10个目录,请设置一些命令别名,例如
alias cdw="cd /var/www/html"
因此,当我想进入Apache主页目录时,我只是键入cdw
以符号链接等效别名的方式回答?。
我正在使用Jump快速更改工作目录。
要添加当前目录:
jump -a [bookmark-name]
列出所有书签:
jump -l
例如:
------------------------------------------------------------------
Bookmark Path
------------------------------------------------------------------
reports ~/mydir/documents/reports
projects ~/documents/projects
dl ~/Downloads
------------------------------------------------------------------
现在,您可以轻松跳转到另一个目录:
jump reports
它支持bash和zsh的自动补全。
编辑(响应@Joe):二进制文件jump-bin
存储在中/usr/local/bin
,并使用bash集成脚本(位于我的PC上/var/lib/gems/1.9.1/gems/jump-0.4.1/bash_integration/shell_driver
)创建一个bash函数jump
,该函数调用jump-bin
。
$CDPATH
也许?