linux目录栈


简介

​ 最近常在服务器上跑任务,但是服务器上跑过的任务太多,工作目录下很多项目的文件,路径也较长,每次进入目标文件夹的时候,即使用tab补全也需要花很多时间来输入绝对路,而每个项目需要的文件夹较少,就固定那么几个,就希望能够暂时将近期常用的文件夹路径暂时存起来,以便调用,换下个项目的时候也可以用新的路径替代老的路径,于是想到了目录栈。


Linux目录栈操作

​ Linux目录栈常用命令有三个,dirs:用于打印目录栈,pushd:用于目录栈的写入和调用,popd:用于目录栈的删除。

dirs

​ dirs命令可以打印当前目录栈下的全部内容。

(base) [yangzhuoxuan@cngb-login-0-1 ~]$ dirs
~ ~/dir2 ~/dir1
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ dirs -l
/home/yangzhuoxuan /home/yangzhuoxuan/dir2 /home/yangzhuoxuan/dir1
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ dirs -p
~
~/dir2
~/dir1
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ dirs -v
 0  ~
 1  ~/dir2
 2  ~/dir1
 
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ dirs -lv
-bash: dirs: -lv: invalid number
dirs: usage: dirs [-clpv] [+N] [-N]
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ dirs -l -v
 0  /home/yangzhuoxuan
 1  /home/yangzhuoxuan/dir2
 2  /home/yangzhuoxuan/dir1
 
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ dirs -c
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ dirs
~

dirs : 打印当前目录栈内容。

​ -l : 显示完整绝对路径,注意第一条是当前路径。

​ -p : 分行打印多条路径。

​ -v : 与 -p 相同,都是分行打印多条路径,但是 -v 参数会在每行前加上索引,可读性更高。其中序号0为当前路径。

​ -c : 清空当前目录栈。由于目录栈第一条是当前路径,清空以后只剩下当前路径。

补充:dirs命令与ls不同,参数不可以合在一起,如果想要分行显示完整绝对路径,需要 -l -v ,不可以 -lv。

补充:dirs -v命令更直观常用,但是命令太长还需要参数不方便输入,可以在配置中别名为dv。

pushd

​ pushd命令可以将路径写入目录栈,也可以进入目录栈中的路径。

​ ※ 由于目录栈第一条( index 为 0 )为当前路径,所以在目录栈第一条路径发生改变时,当前路径也会随之改变到目标路径。

(base) [yangzhuoxuan@cngb-login-0-1 ~]$ dv
 0  ~
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ pushd dir1
~/dir1 ~
(base) [yangzhuoxuan@cngb-login-0-1 dir1]$ pushd ~/dir2
~/dir2 ~/dir1 ~
(base) [yangzhuoxuan@cngb-login-0-1 dir2]$ dv
 0  ~/dir2
 1  ~/dir1
 2  ~

(base) [yangzhuoxuan@cngb-login-0-1 dir2]$ pushd
~/dir1 ~/dir2 ~
(base) [yangzhuoxuan@cngb-login-0-1 dir1]$ dv
 0  ~/dir1
 1  ~/dir2
 2  ~
(base) [yangzhuoxuan@cngb-login-0-1 dir1]$ pushd +1
~/dir2 ~ ~/dir1
(base) [yangzhuoxuan@cngb-login-0-1 dir2]$ pushd +2
~/dir1 ~/dir2 ~
(base) [yangzhuoxuan@cngb-login-0-1 dir1]$ dv
 0  ~/dir1
 1  ~/dir2
 2  ~
(base) [yangzhuoxuan@cngb-login-0-1 dir1]$ pushd -0
~ ~/dir1 ~/dir2

(base) [yangzhuoxuan@cngb-login-0-1 ~]$ dirs -c
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ pushd -n ~/dir1
~ ~/dir1
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ pushd -n lalalala
~ lalalala ~/dir1
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ pushd +1
-bash: pushd: lalalala: No such file or directory

(base) [yangzhuoxuan@cngb-login-0-1 dir1]$ pushd `pwd`
~/dir1 ~/dir1

pushd:调用目录栈内的路径。

​ 直接加路径:将路径加入目录栈的第一条,原目录栈向后顺延。由于改变了第一条路径,当前目录同样发生改变。

​ 不加任何参数:将目录栈 index 为 0 和 1 的路径互调,即目录栈前两条,同时改变当前路径。

​ +Num:注意+和输入Num中没有空格。将目录栈的 index 为 0 和第 Num (即 index 为 Num )的两条路径互调,同时改变当前路径。互调以后目标路径的 index 为 0 ,如果此时再 cd 更改当前路径,则会改变目录栈中的内容,保存在目录栈中的内容将不复存在。

​ -Num:同 +Num ,不过 +Num 是从正着数第 Num 的路径,等同于 index 号码,-Num 是倒着数的,类似 tail 操作,除非目录栈过长时调用在后面的路径,否则并不常用。

​ -n 路径:将输入的文字直接加入目录栈第二条( index 为 1 )。不改变目录栈第一条路径,不更改当前文件夹。注意此操作中不管输入的路径是否存在,都会直接加入目录栈,不进行判断。

补充:如果希望将当前路径加入目录栈,不要使用管道符,可以使用反引号操作。

个人并不是很喜欢这套 pushd 的操作,尤其是会发生当前路径的更改,很不适应,如果 pushd 进入了哪个路径,一旦习惯性 cd 改变了当前文件夹又会损失掉我的目录栈内容。唯一不发生当前路径更改的操作 -n 又不会判断目录是否存在,发生了错误只有切换路径的时候才能发现。

popd

​ popd命令与pushd的添加功能相反,用于删除目录栈中的内容。

(base) [yangzhuoxuan@cngb-login-0-1 ~]$ dv
 0  ~
 1  ~/dir1
 2  ~/dir2
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ popd
~/dir1 ~/dir2
(base) [yangzhuoxuan@cngb-login-0-1 dir1]$ pwd
/home/yangzhuoxuan/dir1

(base) [yangzhuoxuan@cngb-login-0-1 ~]$ dv
 0  ~
 1  ~/dir1
 2  ~/dir2
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ popd ~/dir2
~ ~/dir1

(base) [yangzhuoxuan@cngb-login-0-1 ~]$ dv
 0  ~
 1  ~/dir1
 2  ~/dir2
(base) [yangzhuoxuan@cngb-login-0-1 ~]$ popd +1
~ ~/dir2

popd:删除目录栈内容

​ 不加任何参数:删除目录栈第一条路径内容,同时改变当前目录。

​ 直接加路径:删除目标路径。

​ +Num:注意+和输入Num中没有空格。删除目录栈中第 Num (即 index 为 Num )的路径。

​ -Num:+Num的另一个方向的操作。

​ -n 路径:删除目标路径。

补充:如果 popd 后面添加路径不存在,则会删除目录栈最后一条路径。如果目录栈中有不存在的路径, popd 直接加相同不存在的路径内容,依旧会删除最后一条路径而不删除同名内容,使用 -n 路径 的参数则可以删除同名内容。


自己改进的目录栈

​ Linux自带的目录栈由于种种问题,并不能很好的满足我日常使用。第一,对于一个更改目录使用 cd 成习惯的人,经常在添加目录栈时产生不必要的当前目录跳转,和将目录栈内容的修改,对于个人使用而言,将当前工作目录和目录栈的 index 0 联系起来只带来了许多麻烦。第二, pushd 压入目录栈操作不能保证目录栈中的内容不重复,第三,目录栈对于我最大的不方便在于目录栈不能永久储存,每次重启服务器就会消失,打开多个服务器页面又不能同步。

​ 于是产生了针对自己的需要改进一下目录栈的想法。需要一个文件来储存目录路径,同样类似linux目录栈的操作,需要可以对其打印、目标路径调用,压入和弹出四个操作。

#!/usr/bin/bash

#目录栈存储位置
ds_file=/home/yangzhuoxuan/data/lib/DirectoryStack/list
#不加参数则打印当前目录栈
if [ "$*" == "" ];then
        cat -n ${ds_file}
#参数[-cdn]
elif [[ $1 == -* ]];then
        #参数-n加数字,转到第几个路径
        ##如果路径不存在则从目录栈中删除,防止文件夹删除而目录栈中未删除
        if [ $1 == -n ];then
                if [[ $2 =~ ^[0-9]+$ ]];then
                        dir_name=`sed -n "${2}p" ${ds_file}`
                        if [ -d ${dir_name} ];then
                                echo ${dir_name}
                                cd ${dir_name}
                        else
                                echo "${dir_name} does not exist or is not a directory! Path deleted!"
                                sed -i "${2}d" ${ds_file}
                        fi
                else 
                        echo "$2 is not a number!"
                fi
        #参数-d加数字,从目录栈中删除第几个路径
        elif [ $1 == -d ];then
                if [[ $2 =~ ^[0-9]+$ ]];then
                        dir_name=`sed -n "${2}p" ${ds_file}`
                        echo "Path ${dir_name} deleted!"
                else
                        echo "$2 is not a number!"
                fi
        #参数-c清空目录栈
        elif [ $1 == -c ];then
                > ${ds_file}
        else
                echo "ds: usage: ds [-cdn] or ds pathname"
        fi
#直接加路径,如果路径存在则加入目录栈
##如果路径已在目录栈中则提高位次到第一位
elif [ -d $1 ];then
        dir_name=`lp $1`
        grep_result=`grep -n ^${dir_name}$ ${ds_file}`
        if [ "${grep_result}" != "" ];then
                sed -i "${grep_result%%:*}d" ${ds_file}
        fi
        if [ -s ${ds_file} ];then
                sed -i "1i${dir_name}" ${ds_file}
        else
                echo ${dir_name} > ${ds_file}
        fi
        cat -n ${ds_file}
else
        echo "$1 does not exist or is not a directory!"
fi

​ 简单写了个脚本以完成所需要的操作,将脚本放入bin文件下并赋予可执行权限。

​ 注意:需要储存目录栈的文件存在,虽然- c 参数可以产生文件,但是没有判断其路径的存在。

​ 注意:对于切换当前文件夹操作需要在父进程下运行,建议将“ . ds -n ”在配置文件中别名,以方便切换路径操作。

​ 不算别名的话,用一个命令就可以完成这些操作了,虽然没有linux的目录栈操作功能丰富,但总之能很好的满足我的需求了,而且没有了会偶联当前路径的烦恼,更符合我的操作习惯。也许这个方法效率不是最高的,但是能实现功能就好嘛。终于写好了,上来就先把最近常用的文件夹路径和bin文件路径加在里面了,终于免去了反复输入那些超长路径的烦恼,爽!


文章作者: 七七
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 七七 !
  目录