您的位置:首页 > 运维架构 > Shell

shell程序分析--qcd

2016-03-19 22:31 483 查看
这是国嵌中的一个小应用,目的在于我们能快速的在各个目录之间进行切换。

参考资料:

1、http://pan.baidu.com/s/1dEd1ZFz linux+命令行+shell脚本编程宝典

2、http://www.linuxidc.com/Linux/2014-03/97826.htm 为了解决shell子进程的环境不能传给父进程(!)

下面我将进行详细的源码分析:

qcde:

首先有这几个地方需要注意:

1、脚本开始第一句,用#!+解析器

2、多处用到类似:
[ ! $3 ] || pos=$3
,这个的通用命令为:command1 || command2 [|| command3..]意为,仅在前一个命令输出为false时,执行后一个命令,以此类推。

3、关于重定向 str > $filename ,分清>和>>的区别

4、关于管道 command1 | command2。将前一个命令的输出作为后一个命令的参数。例子有(1)、(2)、(3)等,其中grep处理后得到的是行,awk处理后得到的是列。

5、关于正则表达式,参考上面所给资料

6、子进程不能将环境传给父进程。在(4)、(5)处,
#cd "$enter_dir"  (4)
如果直接用cd 到指定目录时,发现并未反应,原因是,这是所在父进程的一个子进程shell,子进程中是cd到指定目录了,但由于父进程不能继承子进程的环境,所以,父进程的环境依然没有改变。转而,我们先将enter_dir存在QD中。

7、对于问题6怎么解决了,想到了两个思路:既然在执行脚本时,默认会新建一个子进程shell来执行脚本 那我用source file.sh,或者. file.sh不就行了?我试过,直接这样是有问题的,原因大概是,里面涉及到孙进程等。参考2中给了一个解决方法,即给命令,命个别名。alias cdd=’cdd(){ >/tmp/qcd_temp;qcde;if [ $? -eq 0 ];then cd
cat /tmp/qcd_temp
;fi;};cdd’,然后将这个命令加入到/root/.bashrc中。就OK了

若想使它永久生效,只要将其复制到/root/.bash_alias文件中即可

#!/bin/sh
#Quick enter your directory.
#qcd version is 1.00.
#Writen by xiewei 2004.

setup_content=/etc/qcd
history_dir=$setup_content/history_dir

usage()
{
echo "qcd(quick cd) version 1.01 command :"
echo "<qcd -s dir [position]>  add a directory to $history_dir."
echo "if content = ./, then add current directory to  $history_dir."
echo "if position(1-20) is not, default value equal 1."
echo ""
echo "<qcd -d [position]> then delete a directory from $history_dir."
echo "if position is not, default value equal last."
echo ""
echo "<qcd -l [position]> then list directory from $history_dir."
echo  "if position is not, default value equal 1, else list all directory,
then choice one position's content and enter it."
echo ""
echo "<qcd -e [position]> then enter a directory from $history_dir."
echo "if position is not, default value equal 1."
echo ""
echo "<qcd -c> then clear $history_dir."
exit 1
}

handle()
{
line_num=`wc -l $history_dir | awk '{print $1}'` #`wc -l $history_dir` 统计$history_dir所指文件的行数   (1)
h_setup_content=/etc/qcd
h_history_dir=$h_setup_content/history_dir
tmp=$h_setup_content/tmp
pos=1
enter_dir=""

if [ "$1" = "-s" ]
then
[ ! $3 ] || pos=$3    #如果$3为空 pos的值不变,否则pos等于$3
enter_dir=$2    #输入的DIR
[ ! "$2" = "./" ] || enter_dir=`pwd`
[ ! "$2" = "." ] || enter_dir=`pwd`

if [ $pos -gt $line_num ]
then
pos=`expr $line_num + 1`
echo "$pos  $enter_dir" >> $h_history_dir    #将新的dir追加到$h_history_dir
exit 1
fi

[ ! $line_num -eq 0 ] || ! echo "$pos  $enter_dir" >> $h_history_dir || exit 1

flag=""
new_num=0
> $tmp    #将$tmp清空
cat $h_history_dir | while read num content
do# (2)
new_num=`expr $new_num + 1`
[ ! $flag ] || num=`expr $num + 1`    #当新添加了一行的时候$new_num + 1
[ ! $num -gt 20 ] || exit 1    #当$tmp里面有20行的时候就结束

if [ $num -eq $pos ]
then
flag="have"
echo "$pos  $enter_dir" >> $tmp
new_num=`expr $new_num + 1`
echo "$new_num  $content" >> $tmp
else
echo "$new_num  $content" >> $tmp
fi
done

mv $tmp $h_history_dir
fi
#*****************************************************************************
if [ "$1" = "-l" ]
then
[ ! $2 ] || ! pos=$2 || ! cat $h_history_dir | grep "^$pos " || exit 1    #^只允许在一行的开始匹配字符或单词,grep检测输入 (3)

cat  $h_history_dir
fi
#*****************************************************************************
if [ "$1" = "-e" ]
then
if [ $2 ]
then
for x in `cat $h_history_dir | awk '{print $1}'`
do
if [ "$x" = "$2" ]
then
enter_dir=`cat $h_history_dir | grep "$2 " | awk '{print $2}'`
echo "$enter_dir" > $QD
#cd "$enter_dir"  (4)
exit 1
fi
done

cat  $h_history_dir
echo "Not content number $2"
exit 1
fi

cat  $h_history_dir
echo -n "Press <Enter> to exit or enter your choice(1-$line_num/q/Q/): "

while read choice
do
if [ "$choice" = "q"  -o  "$choice" = "Q" ]
then
echo "Nothing to do!"
exit 1
fi

[ "$choice" ] ||
{
echo "Nothing to do!"
exit 1
}

for x in `cat $h_history_dir | awk '{print $1}'`
do
if [ "$x" = "$choice" ]
then
enter_dir=`cat $h_history_dir | grep "$choice " | awk '{print $2}'`
echo "$enter_dir" > $QD
#cd "$enter_dir"  (5)
exit 1
fi
done

echo -n "Press <Enter> to exit or enter your choice(1-$line_num/q/Q/): "
done
fi
#*****************************************************************************
if [ "$1" = "-d" ]
then
pos=$line_num
[ ! $2 ] || pos=$2
[ ! $pos -gt $line_num ] || ! echo "in $h_history_dir, only have $line_num  contents " || exit

new_num=0
> $tmp
cat $h_history_dir | while read num content
do
new_num=`expr $new_num + 1`

if [ $num -eq $pos ]
then
new_num=`expr $new_num - 1`
echo "delete: $num  $content"
else
echo "$new_num  $content" >> $tmp
fi
done

mv $tmp $h_history_dir
fi
#*****************************************************************************
if [ "$1" = "-c" ]
then
echo -n "Are you sure to clear $h_history_dir(y\Y or q\Q)? "
while read choice
do
if [ "$choice" = "y"  -o  "$choice" = "Y" ]
then
> $h_history_dir
echo "clear $h_history_dir OK!"
exit 1
fi

if [ "$choice" = "q"  -o  "$choice" = "Q" ]
then
echo "Nothing to do!"
exit 1
fi

echo -n "Are you sure to clear $h_history_dir(y\Y or q\Q)? "
done
fi
}

[ $# -eq 0  ] &&  handle -e #传入参数的个数等于0,

if [ $# -gt 3 ]
then
usage
fi

case $1 in
-s)
[ $2 ] || usage
handle $1 $2 $3
;;
-d)
[ ! $3 ] || usage
handle $1 $2
;;
-l)
[ ! $3 ] || usage
handle $1 $2
;;
-e)
[ ! $3 ] || usage
handle $1 $2
;;
-c)
[ ! $3 ] || usage
[ ! $2 ] || usage
handle $1
;;
*)
usage
;;
esac
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: