linux下便捷高效地切换当前工作目录的技巧及脚本
在linux下进行目录的频繁切换通常会用到dirs,pushd,popd等命令,但这样也会比较的繁琐;
本文通过linux基本命令封装了一个脚本,加载后只需通过一个djump命令即可完成目录的快速跳转;
使用方式,
首先source加载,可以直接写入 ~/.bashrc文件登录时自动加载;
比如保存为~/env/djump.sh文件,然后将这条语句写入~/.bashrc文件中
[ -f ~/env/djump.sh ] && source ~/env/djump.sh
然后直接可以通过djump --help查看释放方法
执行djump --help查看使用帮助
可以快速的对所在目录创建tag,以及快速的跳转到指定tag所代表的目录;
#! /bin/bash
#
####################################################
# Filename : djump.sh
# Author : longbin
# Created date: 2017-03-31 19:16:19
####################################################
#
# change history
# v1.1 2020-05-04 merge dtag and duntag to djump --create, --delete.
# v1.2 2020-06-08 update interaction message.
# v1.3 2021-12-06 optimise process for 'OLDPWD not set'.
# v1.4 2022-03-25 update help info and comment.
# v1.5 2022-09-28 add color print for output.
# v1.6 2022-10-08 fix tag output alignment issue.
export __DJUMP_VERSION='v1.6'
export __DJUMP_DATA_PATH=${HOME}/.djump
[ -d ${__DJUMP_DATA_PATH} ] || mkdir -p ${__DJUMP_DATA_PATH} 2>/dev/null
function _djump_print_with_width()
{
local min_width=${1}
local tag_name=${*}
tag_name=${tag_name#* } # remove 1st arg
local out_length=${#tag_name}
local blanks=' '
for ((;out_length<min_width;out_length++))
do
# append blank
blanks="${blanks}"' '
done
echo -n -e "${tag_name}${blanks}"
}
function _djump_list_tags()
{
local tag_name=$1
local tag_len=${#tag_name}
local tag_matched=""
local link_short_name=''
local link_long_path=''
local link_name_length=0
local column_sep_ok='--->'
local column_sep_ng='---x'
local data_path=${__DJUMP_DATA_PATH}
local tag_print_width=7
local color_print=1
# close color print for some terminal type
case "${TERM}" in
"xterm")
color_print=0
;;
*);;
esac
# echo "_djump_list_tags tag:${tag_name}, begin."
# update tag_print_width
local tag_list_details=$(ls -l --color=never ${data_path} | \
awk '{
if ($(NF-1)=="->") {
print $(NF-2)"->"$(NF)
}
}')
# match tag_name and set print width
for line in ${tag_list_details}
do
link_short_name=$(echo ${line} | awk -F'->' '{print $1}')
if [ "${link_short_name:0:${tag_len}}" = "${tag_name}" ] ;then
tag_matched="ok"
fi
if [ "${color_print}" != "0" ] ;then
link_short_name="\033[36m${link_short_name}\033[0m"
fi
link_name_length=${#link_short_name}
if [ "${link_name_length}" -gt "${tag_print_width}" ] ;then
let tag_print_width=${link_name_length}
fi
done
# no matched tag found
if [ "${tag_matched}" != "ok" ] ;then
tag_name=''
fi
# show detailed info of each tag
for line in ${tag_list_details}
do
link_short_name=$(echo ${line} | awk -F'->' '{print $1}')
link_long_path=$(echo ${line} | awk -F'->' '{print $2}')
if [ "${link_short_name}" = "" ] ;then
continue
fi
# echo "tag: ${tag_name}, link: ${link_short_name}"
# if tag_name is not empty, show the specified tag info
# else show each tag info
if [ "${tag_name}" != "" ] ;then
if [ "${tag_name}" != "${link_short_name:0:${tag_len}}" ] ;then
continue
fi
fi
# show tag name
if [ "${color_print}" != "0" ] ;then
link_short_name="\033[36m${link_short_name}\033[0m"
fi
_djump_print_with_width ${tag_print_width} ${link_short_name}
# show detailed link path
if [ -d ${link_long_path} ] ;then
if [ "${color_print}" != "0" ] ;then
link_long_path="\033[34m${link_long_path}\033[0m"
fi
_djump_print_with_width 0 "${column_sep_ok} ${link_long_path}"
else
if [ "${color_print}" != "0" ] ;then
link_long_path="\033[40;31m${link_long_path}\033[0m"
fi
_djump_print_with_width 0 "${column_sep_ng} ${link_long_path}"
fi
echo ""
done
}
function djump()
{
local argv1=$1
local argv2=$2
local argv3=$3
local data_path=${__DJUMP_DATA_PATH}
local help_info="djump ${__DJUMP_VERSION}
This tool can change work directory more easy and quickly.
Usage:
djump [option] [tag_name]
Options:
-j, --jump
change directory to the tag_name represented.
change directory to the last one if no tag_name specified.
this is the default option.
-l, --list
list tags named like tag_name.
list all tags when no tag_name specified.
-c, --create
create tag named as tag_name.
tag_name cannot start with (-);
-d, --delete
delete tag named as tag_name;
Examples:
djump change directory to the last one;
djump -j change directory to the last one;
djump --jump change directory to the last one;
djump tag_name change directory to the tag_name represented;
djump -j tag_name change directory to the tag_name represented;
djump --jump tag_name change directory to the tag_name represented;
djump -l list all tags created;
djump --list list all tags created;
djump -l tag_name list tag named like tag_name;
djump --list tag_name list tag named like tag_name;
djump -c tag_name create tag named as tag_name, tag_name cannot start with (-);
djump --create tag_name create tag named as tag_name, tag_name cannot start with (-);
djump -d tag_name delete tag named as tag_name;
djump --delete tag_name delete tag named as tag_name;
"
# show help info when argument is one of ?,-h,--help
for arg in "$@"
do
# echo ${arg}
case "${arg,,}" in
'?')
echo -e "${help_info}"
return 0
;;
'--help'|'-h')
echo -e "${help_info}"
return 0
;;
esac
done
[ -d ${data_path} ] || mkdir -p ${data_path}
if [ "$?" != "0" ] ;then
echo "Error: permission denied."
return 1
fi
# if no arg: cd -;
# if only one arg: cd arg;
# if option1 in ["--create", "--delete", "--list"] and has arg: do action with arg
# otherwise show help info and options.
if [ "${argv1:0:1}" = "-" ] ;then
option1=${argv1}
tag_name=${argv2}
butt_arg=${argv3}
else
option1='--jump' # jump is the default option.
tag_name=${argv1}
butt_arg=${argv2}
fi
if [ "${tag_name:0:1}" = "-" ] ;then
echo "Error: invalid tag_name: cannot start with (-)"
echo -e "${help_info}"
return 1
fi
# butt_arg should be empty, the cmd at most has cmd, opt, tag.
if [ "${butt_arg}" != "" ] ;then
echo "Error: invalid parameters."
# show all created tag
echo -e "${help_info}"
return 1
fi
case "${option1,,}" in
'-j'|'--jump')
# jump
if [ "${tag_name}" = '' ] ;then
if [ "${OLDPWD}" != '' ] ;then
cd -
fi
return 0
fi
if [ -L ${data_path}/${tag_name} ] ;then
if [ ! -d ${data_path}/${tag_name} ] ;then
# tag_name is a link file targeted to an invalid directory: invalid link.
echo "Error: ${tag_name}: Invalid source directory."
return 1
fi
# change directory to the path that tag represented.
cd -P ${data_path}/${tag_name} 2>/dev/null
if [ "$?" != "0" ] ;then
echo "Error: ${tag_name}: Invalid tag."
return 1
fi
else
echo "Error: ${tag_name}: No such tag."
if [ "$(ls ${data_path})" != "" ] ;then
echo -e "\nThe tag_name could be:"
for line in $(ls ${data_path})
do
echo -e " ${line}"
done
fi
return 1
fi
;;
'-c'|'--create')
# create tag
if [ "${tag_name}" = "" ] ;then
echo "Error: Invalid tag_name: cannot be empty."
echo -e "${help_info}"
return 1
fi
if [ -L ${data_path}/${tag_name} ] ;then
echo "${tag_name}: already exists."
read -p "update the tag ${tag_name} to $(pwd)? [y/N] " choice
if [ "${choice,,}" = "y" ] ;then
rm -f ${data_path}/${tag_name}
else
return
fi
fi
# create a soft link to $(pwd) with the tag_name
ln -s $(pwd) ${data_path}/${tag_name} 2>/dev/null
if [ "$?" != "0" ] ;then
echo "Error: permission denied."
return 1
fi
;;
'-d'|'--delete')
if [ "${tag_name}" = "" ] ;then
echo "Error: Invalid tag_name: cannot be empty."
# show all created tag_name
echo -e "${help_info}"
if [ "$(ls ${data_path})" != "" ] ;then
echo -e "\nThe tag_name could be:"
for line in $(ls ${data_path})
do
echo -e " ${line}"
done
fi
return 1
fi
# delete tag_name link file if tag_name exists.
if [ -L ${data_path}/${tag_name} ] ;then
read -p "remove tag: \`${tag_name}'? [y/N] " choice
if [ "${choice,,}" = "y" ] ;then
rm -f ${data_path}/${tag_name} 2>/dev/null
if [ "$?" != "0" ] ;then
echo "Error: permission denied."
return 1
fi
fi
else
echo "Error: ${tag_name}: No such tag."
return 1
fi
;;
'-l'|'--list')
# list the specified tag info of tags start with tag_name,
# or all tag info if empty tag_name or non-matched tag_name.
_djump_list_tags ${tag_name}
;;
*)
echo "${option1}: Invalid option."
echo -e "${help_info}"
return 1
;;
esac
return 0
}
# to provide completion word for djump when double hit tab.
function _djump_completer()
{
# compgen -W will match words starting with cur_word from word_list.
# Command: compgen –w “aa ab bb cc” -- “a”;
# means to match words starting with "a" from "aa ab bb cc",
# The return result of this command is "aa ab".
# COMP_CWORD is a system variable that indicates the current word index in command.
local cur_word=${COMP_WORDS[COMP_CWORD]}
local word_list=$(find ${__DJUMP_DATA_PATH} -maxdepth 1 -type l -printf "%f\n")
#COMPREPLY=($(compgen -W '${word_list[@]}' -- "${cur_word}"))
# echo -e "\n\t cmd is ${COMP_WORDS[0]}"
# echo -e "\t argv1 is ${COMP_WORDS[1]}"
# echo -e "\t argv2 is ${COMP_WORDS[2]}"
# echo -e "${COMP_WORDS[0]}, ${COMP_WORDS[1]}\c"
case ${COMP_CWORD} in
0) #command hasnt been completed yet, nothing to do here.
#${COMP_WORDS[0]} is argv0(that is cmd).
;;
1) #command has been completed, begin to complete argv1.
#${COMP_WORDS[0]} is command.
#${COMP_WORDS[1]} is argv1.
argv1=${COMP_WORDS[1]}
if [ "${argv1:0:1}" = '-' ] ;then
local option_list='-j --jump -c --create -d --delete -l --list'
COMPREPLY=($(compgen -W '${option_list}' -- "${cur_word}"))
else
COMPREPLY=($(compgen -W '${word_list[@]}' -- "${cur_word}"))
fi
;;
2|*)#command and argv1 have been completed, begin to complete argv2.
#${COMP_WORDS[1]} is argv1.
case ${COMP_WORDS[1]} in
'-j'|'--jump')
COMPREPLY=($(compgen -W '${word_list[@]}' -- "${cur_word}"))
;;
'-d'|'--delete')
COMPREPLY=($(compgen -W '${word_list[@]}' -- "${cur_word}"))
;;
'-l'|'--list')
COMPREPLY=($(compgen -W '${word_list[@]}' -- "${cur_word}"))
;;
*)
;;
esac
;;
esac
}
complete -F _djump_completer djump
例如
[~]$ djump --help
djump v1.6
This tool can change work directory more easy and quickly.
Usage:
djump [option] [tag_name]
Options:
-j, --jump
change directory to the tag_name represented.
change directory to the last one if no tag_name specified.
this is the default option.
-l, --list
list tags named like tag_name.
list all tags when no tag_name specified.
-c, --create
create tag named as tag_name.
tag_name cannot start with (-);
-d, --delete
delete tag named as tag_name;
Examples:
djump change directory to the last one;
djump -j change directory to the last one;
djump --jump change directory to the last one;
djump tag_name change directory to the tag_name represented;
djump -j tag_name change directory to the tag_name represented;
djump --jump tag_name change directory to the tag_name represented;
djump -l list all tags created;
djump --list list all tags created;
djump -l tag_name list tag named like tag_name;
djump --list tag_name list tag named like tag_name;
djump -c tag_name create tag named as tag_name, tag_name cannot start with (-);
djump --create tag_name create tag named as tag_name, tag_name cannot start with (-);
djump -d tag_name delete tag named as tag_name;
djump --delete tag_name delete tag named as tag_name;
[~]$
[~]$ cd /mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$ djump -c locservice.code
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$ cd
[~]$
[~]$ djump locservice.code
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$ djump
[~]$
[~]$ djump
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$ djump
[~]$
[~]$ cd /mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$ djump -c locservice.build
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$ djump #连续按下[TAB][TAB]
locservice.build locservice.code
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$ djump locservice.code
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$ djump locservice.build
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$ djump
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server]$ djump
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$ djump -l
locservice.build ----> /mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core
locservice.code ----> /mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core/java/com/android/server
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$
[/mnt/android_code/code/v3.0/andrdoi_9.0/AOSP/frameworks/base/services/core]$