Vol*_*ike 47 bash administration shell-script
在系统管理的多个目录之间切换的快速命令行方式是什么?我的意思是,我可以使用pushd .和popd来切换,但是如果我想存储倍数并在它们之间循环,而不是永久地将它们从堆栈底部弹出怎么办?
agc*_*agc 42
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 ; }
Run Code Online (Sandbox Code Playgroud)
测试:设置四个目录的堆栈。
dirs -c # clear directory stack
cd /home ; pushd /etc ; pushd /bin ; pushd /tmp
Run Code Online (Sandbox Code Playgroud)
现在/tmp是当前目录,堆栈看起来像:
/tmp /bin /etc /home
Run Code Online (Sandbox Code Playgroud)
切换到堆栈中的下一个目录(并显示它),四次:
ncd ; pwd ; ncd ; pwd ; ncd ; pwd ; ncd ; pwd
Run Code Online (Sandbox Code Playgroud)
输出:
/bin
/etc
/home
/tmp
Run Code Online (Sandbox Code Playgroud)
更改到堆栈中的上一个目录(并显示),四次:
pcd ; pwd ; pcd ; pwd ; pcd ; pwd ; pcd ; pwd
Run Code Online (Sandbox Code Playgroud)
输出:
/home
/etc
/bin
/tmp
Run Code Online (Sandbox Code Playgroud)
关于cd -:通配符的回答帮助说明了如何cd -不使用$DIRSTACK数组(它使用$OLDPW变量),因此它cd -不会像基于堆栈的交换那样影响$DIRSTACK。为了纠正这个问题,这里有一个简单的基于$DIRSTACK的交换函数:
scd() { { pushd ${DIRSTACK[1]} ; popd -n +2 ; } > /dev/null ; }
Run Code Online (Sandbox Code Playgroud)
测试:
dirs -c; cd /tmp; \
pushd /bin; \
pushd /etc; \
pushd /lib; \
pushd /home; \
scd; dirs; scd; dirs
Run Code Online (Sandbox Code Playgroud)
输出:
/bin /tmp
/etc /bin /tmp
/lib /etc /bin /tmp
/home /lib /etc /bin /tmp
/lib /home /etc /bin /tmp
/home /lib /etc /bin /tmp
Run Code Online (Sandbox Code Playgroud)
Wil*_*ard 30
用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 $
Run Code Online (Sandbox Code Playgroud)
这种方式最有效的使用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 ~-
Run Code Online (Sandbox Code Playgroud)
以上相当于:
cp /another/long/path/to/where/the/source/file/is/myfile /very/long/path/to/some/directory/
Run Code Online (Sandbox Code Playgroud)
RJH*_*ter 11
当您在cd某个地方时,Bash 会将旧的工作目录存储为环境变量$OLDPWD.
您可以使用 切换回该目录cd -,相当于cd "$OLDPWD".
您可以像这样在目录之间来回弹跳:
blue$ cd ~/green
green$ cd -
blue$ cd -
green$
Run Code Online (Sandbox Code Playgroud)
我写了一个名为的脚本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
Run Code Online (Sandbox Code Playgroud)
我使用它的方法是复制到/usr/bin文件夹中,然后chmod a+x在它上面。然后,我编辑我的 root 和用户帐户~/.bashrc文件以在底部包含这些行:
alias xyzzy='. xyzzy'
alias xy='. xyzzy'
Run Code Online (Sandbox Code Playgroud)
'xy' 是命令的缩写形式,用于加快输入速度。
然后,我可以将当前目录存储在列表中...
xyzzy this
Run Code Online (Sandbox Code Playgroud)
...并根据需要重复。一旦我用我需要的目录填写了这个列表,它们就会保留在那里,直到我重新启动计算机,因为那时 /tmp 再次被清除。然后我可以输入...
xyzzy show
Run Code Online (Sandbox Code Playgroud)
...列出当前保存的目录。为了切换到一个目录,我有两个选择。一种选择是按索引指定路径(它是一个基于 1 的索引),如下所示:
xyzzy 2
Run Code Online (Sandbox Code Playgroud)
...这将切换到列表中的第二个项目的目录。或者,我可以不使用索引号而只执行以下操作:
xyzzy
Run Code Online (Sandbox Code Playgroud)
...让它根据需要循环遍历每个目录。要获取更多可以执行的命令,请键入:
xyzzy help
Run Code Online (Sandbox Code Playgroud)
当然,使用我添加的愚蠢的 echo 语句,工作会更有趣。
请注意,xyzzy 是对Collosal Cave文本冒险的引用,在其中键入 xyzzy 将让您在游戏中的两个房间之间切换,以避免发生骚乱。
也有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
Run Code Online (Sandbox Code Playgroud)
简单地用于cd --显示过去最多 10 个您访问过的目录的列表,cd并且cd -N(N条目的索引在哪里)到那里去。
我使用了一个名为 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.
Run Code Online (Sandbox Code Playgroud)