linux脚本学习系列将以一系列实际脚本来讲解,在对脚本分析的过程中学习bash语言的使用。
话不多说,直接上脚本:
#!/bin/bash
# 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
#如果参数1为“--”,则显示目录栈信息,并返回
if [[ $1 == "--" ]]; then
dirs -v
return 0
fi
#如果参数1为空,则the_new_dir等于home路径。
the_new_dir=$1
[[ -z $1 ]] && the_new_dir=$HOME
#判断the_new_dir的第一个字符是否为"-"
if [[ ${the_new_dir:0:1} == '-' ]]; then
#
# Extract dir N from dirs
#提取the_new_dir从1到最后的字符给index
index=${the_new_dir:1}
#如果只输入-,则index默认为1
[[ -z $index ]] && index=1
#提取目录栈中的第index个目录给adir
adir=$(dirs +$index)
#如果adir为空则返回
[[ -z $adir ]] && return 1
#否则the_new_dir为获得的目录
the_new_dir=$adir
fi
#
# '~' has to be substituted by ${HOME}
#如果the_new_dir的首字符为~,则用目录栈中对应的the_new_dir后几个来替换
[[ ${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
#进入the_new_dir路径,并将the_new_dir复制到栈顶
pushd "${the_new_dir}" > /dev/null
[[ $? -ne 0 ]] && return 1
the_new_dir=$(pwd)
#
# Trim down everything beyond 11th entry
# 这里有个问题,实际中运行的只是剔除了第11个索引值
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
这个脚本只有一个函数cd_func,这个函数实现了一系列好用的路径切换功能,然后用alias,别名功能讲cd_func取名为日常使用的cd,这样符合我们的日常使用习惯。
在脚本的最后判断如果当前bash的版本号大于2.05a时,就将cd_func --这个指令与Ctrl+w绑定起来。
bind命令用于显示和设置命令行的键盘序列绑定功能。通过这一命令,可以提高命令行中操作效率。可以利用bind命令了解有哪些按键组合与其功能,也可以自行指定要用哪些按键组合.
选项介绍:
选项 | 用途 |
---|---|
-d | 显示按键配置内容 |
-f<按键配置文件> | 载入指定的按键配置文件 |
-l | 列出所有功能 |
-m<按键配置> | 指定按键配置 |
-q<功能> | 显示指定功能的按键 |
-v | 列出目前的按键配置及其功能 |
-x <按键> | 绑定按键与功能 |
下面我们使用bind -x来进行试验:
#绑定ctrl+l实现ls -l功能
bind -x ‘“\C-l”:ls -l’
接下来我们将详细分析cd_func函数。
首先看函数的前两行:
local x2 the_new_dir adir index
local -i cnt
local作用为在函数内定义局部变量,因此这两行作用是定义了一系列的局部变量。
if [[ $1 == "--" ]]; then
dirs -v
return 0
fi
这里有一个if语句,如果满足传入的第一个参数为"–",的话就执行dirs -v。
dirs作用为显示当前目录栈,目录栈是最近访问目录的列表。
其选项如下:
选项 | 作用 |
---|---|
-c | 清除目录栈 |
-l | 显示完整的目录信息,而不是用~表示home目录 |
-p | 以每个目录一行的方式显示路径 |
-v | 在-p的基础上显示每个目录在目录栈中的索引 |
+N | 显示从小到大排序,第N个索引的路径 |
-N | 显示从大到小排序,第N个索引的路径 |
这个if语句的作用是如果传入的第一个参数为–,就显示当前的目录栈。
the_new_dir=$1
[[ -z $1 ]] && the_new_dir=$HOME
这里为判断$1是否为空,如果为空就将the_new_dir等于home路径.
在判断中-z表示空的意思。
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
t h e n e w d i r : 0 : 1 的 作 用 为 提 取 t h e n e w d i r 中 第 一 个 字 符 ; {the_new_dir:0:1}的作用为提取the_new_dir中第一个字符; thenewdir:0:1的作用为提取thenewdir中第一个字符;{the_new_dir:n}的作用为提取the_new_dir从n到最后的字符。
[[ ${the_new_dir:0:1} == '~' ]] && the_new_dir="${HOME}${the_new_dir:1}"
在linux下~n表示目录栈中序号n的目录。
pushd "${the_new_dir}" > /dev/null
[[ $? -ne 0 ]] && return 1
the_new_dir=$(pwd)
pushd指令将当前的路径复制到目录栈的栈顶,但原来索引位置还是保留原路径信息;
"> /dev/null"表示将pushd产生的打印信息不输出.
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
将目录栈中与栈顶一样的路径删除。
OK,这样我们就搞明白了这个脚本的逻辑,并学到了新的bash命令。