高级Bash脚本编程指南(19):内部命令与内建命令(二)

高级Bash脚本编程指南(19):内部命令与内建命令(二)

成与坚持,败于止步

文件系统

cd

cd, 修改目录命令, 在脚本中用的最多的时候就是当命令需要在指定目录下运行时, 需要用它来修改当前工作目录.

这里只是提一下比较特殊的情况,也许你不是很常用这些

cd - 将会把工作目录修改至$OLDPWD, 也就是之前的工作目录.

root@haitao-VirtualBox:~# cd mysrc/
root@haitao-VirtualBox:~/mysrc# cd -
/root
root@haitao-VirtualBox:~# cd mysrc/
root@haitao-VirtualBox:~/mysrc# cd /root/myshare/
root@haitao-VirtualBox:~/myshare# cd -
/root/mysrc
root@haitao-VirtualBox:~/mysrc# 
当我们使用两个"/"来作为cd命令的参数时, 结果却出乎我们的意料,当然单个“/”是没有问题的

root@haitao-VirtualBox:~/mysrc# cd /
root@haitao-VirtualBox:/# cd 
root@haitao-VirtualBox:~# cd //
root@haitao-VirtualBox://# pwd
//
root@haitao-VirtualBox://# 

pwd

打印出当前的工作目录. 这将给出用户(或脚本)的当前工作目录 , 使用这个命令的结果和从内建变量$PWD中所读取的值是相同的.

pushd, popd, dirs

这几个命令可以使得工作目录书签化, 就是可以按顺序向前或向后移动工作目录. 压栈的动作可以保存工作目录列表. 选项可以允许对目录栈做不同的操作.

pushd dir-name把路径dir-name压入目录栈, 同时修改当前目录到dir-name.

popd将目录栈最上边的目录弹出, 同时将当前目录修改为刚弹出来的那个目录.

dirs列出所有目录栈的内容 (与$DIRSTACK变量相比较). 一个成功的pushd或者popd将会自动调用dirs命令.

对于那些并没有对当前目录做硬编码, 并且需要对当前工作目录做灵活修改的脚本来说, 使用这些命令是再好不过了. 注意内建$DIRSTACK数组变量, 这个变量可以在脚本中进行访问, 并且它们保存了目录栈的内容.

root@ubuntu:~/resource/shell-study/0614-2013# pushd `pwd`
~/resource/shell-study/0614-2013 ~/resource/shell-study/0614-2013
root@ubuntu:~/resource/shell-study/0614-2013# cd 
root@ubuntu:~# popd
~/resource/shell-study/0614-2013
root@ubuntu:~/resource/shell-study/0614-2013# dirs
~/resource/shell-study/0614-2013
root@ubuntu:~/resource/shell-study/0614-2013# 

看一个修改当前工作目录的实例

#!/bin/bash

dir1=/usr/local
dir2=/var/spool

pushd $dir1
# 将自动运行一个 'dirs' (把目录栈的内容列到stdout上).
echo "Now in directory `pwd`." # 使用后置引用的 'pwd'.

# 现在对'dir1'做一些操作.
pushd $dir2
echo "Now in directory `pwd`."

# 现在对'dir2'做一些操作.
echo "The top entry in the DIRSTACK array is $DIRSTACK."
popd
echo "Now back in directory `pwd`."

# 现在, 对'dir1'做更多的操作.
popd
echo "Now back in original working directory `pwd`."

exit 0
结果:

root@ubuntu:~/resource/shell-study/0615-2013# chmod +x test1.sh 
root@ubuntu:~/resource/shell-study/0615-2013# ./test1.sh 
/usr/local ~/resource/shell-study/0615-2013
Now in directory /usr/local.
/var/spool /usr/local ~/resource/shell-study/0615-2013
Now in directory /var/spool.
The top entry in the DIRSTACK array is /var/spool.
/usr/local ~/resource/shell-study/0615-2013
Now back in directory /usr/local.
~/resource/shell-study/0615-2013
Now back in original working directory /root/resource/shell-study/0615-2013.
root@ubuntu:~/resource/shell-study/0615-2013# 
没什么难的,静下心来分析一下就清楚了

变量

let

let命令将执行变量的算术操作. 在许多情况下, 它被看作是复杂的expr命令的一个简化版本.

一个使用"let"命令来做算术运算的实例

#!/bin/bash

echo

let a=11            # 与 'a=11' 相同
let a=a+5           # 等价于 let "a = a + 5"
                    # (双引号和空格是这句话更具可读性.)
echo "11 + 5 = $a"  # 16

let "a <<= 3"       # 等价于 let "a = a << 3"
echo "\"\$a\" (=16) left-shifted 3 places = $a"
                    # 128

let "a /= 4"        # 等价于 let "a = a / 4"
echo "128 / 4 = $a" # 32

let "a -= 5"        # 等价于 let "a = a - 5"
echo "32 - 5 = $a"  # 27

let "a *=  10"      # 等价于 let "a = a * 10"
echo "27 * 10 = $a" # 270

let "a %= 8"        # 等价于 let "a = a % 8"
echo "270 modulo 8 = $a  (270 / 8 = 33, remainder $a)"
                    # 6

echo

exit 0
结果:
root@ubuntu:~/resource/shell-study/0615-2013# chmod +x test2.sh 
root@ubuntu:~/resource/shell-study/0615-2013# ./test2.sh 

11 + 5 = 16
"$a" (=16) left-shifted 3 places = 128
128 / 4 = 32
32 - 5 = 27
27 * 10 = 270
270 modulo 8 = 6  (270 / 8 = 33, remainder 6)

root@ubuntu:~/resource/shell-study/0615-2013# 
eval

eval arg1 [arg2] ... [argN]

将表达式中的参数, 或者表达式列表, 组合起来, 然后评价它们, 任何被包含在表达示中的变量都将被扩展. 结果将会被转化到命令中. 如果你想从命令行中或者是从脚本中产生代码, 那么这个命令就非常有用了.

root@ubuntu:~/resource/shell-study/0615-2013# process=xterm
root@ubuntu:~/resource/shell-study/0615-2013# show_process="eval ps ax | grep $process"
root@ubuntu:~/resource/shell-study/0615-2013# $show_process
30030 pts/0    S+     0:00 grep --color=auto xterm

一个展示eval命令的效果的实例

#!/bin/bash

y=`eval ls -l`  #  与 y=`ls -l` 很相似
echo $y         #+ 但是换行符将会被删除, 因为"echo"的变量未被""引用.
echo
echo "$y"       #  用""将变量引用起来, 换行符就不会被空格替换了.

echo; echo

y=`eval df`     #  与 y=`df` 很相似
echo $y         #+ 换行符又被空格替换了.

#  当没有LF(换行符)出现时, 如果使用"awk"这样的工具来分析输出的结果,
#+ 应该能更容易一些.

echo
echo "==========================================================="
echo

# 现在,来看一下怎么用"eval"命令来"扩展"一个变量 . . .

for i in 1 2 3 4 5; do
  eval value=$i
  #  value=$i 具有相同的效果, 在这里并不是非要使用"eval"不可.
  #  一个缺乏特殊含义的变量将被评价为自身 -- 也就是说,
  #+ 这个变量除了能够被扩展成自身所表示的字符外, 不能被扩展成任何其他的含义.
  echo $value
done

echo
echo "---"
echo

for i in ls df; do
  value=eval $i
  #  value=$i 在这里就与上边这句有了本质上的区别.
  #  "eval" 将会评价命令 "ls" 和 "df" . . .
  #  术语 "ls" 和 "df" 就具有特殊含义,
  #+ 因为它们被解释成命令,
  #+ 而不是字符串本身.
  echo $value
done


exit 0
结果:
root@ubuntu:~/resource/shell-study/0615-2013# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1             19737268   7480724  11253948  40% /
none                    508764       276    508488   1% /dev
none                    512996        12    512984   1% /dev/shm
none                    512996       120    512876   1% /var/run
none                    512996         0    512996   0% /var/lock
none                    512996         0    512996   0% /lib/init/rw
root@ubuntu:~/resource/shell-study/0615-2013# chmod +x test3.sh root@ubuntu:~/resource/shell-study/0615-2013# ./test3.sh total 12 -rwxr-xr-x 1 root root 508 2013-06-14 23:08 test1.sh -rwxr-xr-x 1 root root 693 2013-06-14 23:13 test2.sh -rwxr-xr-x 1 root root 1262 2013-06-14 23:24 test3.sh

total 12
-rwxr-xr-x 1 root root  508 2013-06-14 23:08 test1.sh
-rwxr-xr-x 1 root root  693 2013-06-14 23:13 test2.sh
-rwxr-xr-x 1 root root 1262 2013-06-14 23:24 test3.sh


Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda1 19737268 7480736 11253936 40% / none 508764 276 508488 1% /dev none 512996 12 512984 1% /dev/shm none 512996 120 512876 1% /var/run none 512996 0 512996 0% /var/lock none 512996 0 512996 0% /lib/init/rw

===========================================================

1
2
3
4
5

---

test1.sh  test2.sh  test3.sh
5
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1             19737268   7480736  11253936  40% /
none                    508764       276    508488   1% /dev
none                    512996        12    512984   1% /dev/shm
none                    512996       120    512876   1% /var/run
none                    512996         0    512996   0% /var/lock
none                    512996         0    512996   0% /lib/init/rw
5
root@ubuntu:~/resource/shell-study/0615-2013#
强制登出(log-off)实例

#!/bin/bash
# 结束ppp进程来强制登出log-off.

# 本脚本应该以root用户的身份来运行.

killppp="eval kill -9 `ps ax | awk '/ppp/ { print $1 }'`"
#                     -------- ppp的进程ID -------

$killppp                  # 这个变量现在成为了一个命令.


# 下边的命令必须以root用户的身份来运行.

chmod 666 /dev/ttyS3 
#  因为在ppp上执行一个SIGKILL将会修改串口的权限,
#+ 我们把权限恢复到之前的状态.

rm /var/lock/LCK..ttyS3   # 删除串口琐文件.

exit 0
eval命令是有风险的, 如果你有更合适的方法来实现功能的话, 尽量避免使用它. eval $COMMANDS将会执行命令COMMANDS的内容, 如果命令中包含有rm -rf *这样的东西, 可能就不是你想要的了. 当你运行一个包含有eval命令的陌生人所编写的代码片段的时候, 这是一件很危险的事情.

set

set命令用来修改内部脚本变量的值. 它的一个作用就是触发选项标志位来帮助决定脚本的行为. 另一个作用是以一个命令的结果(set `command`)来重新设置脚本的位置参数. 脚本将会从命令的输出中重新分析出位置参数.

一个使用set命令来改变脚本的位置参数的实例

#!/bin/bash

# 使用3个命令行参数来调用这个脚本,
# 比如, "./test one two three".

echo
echo "Positional parameters before  set \`uname -a\` :"
echo "Command-line argument #1 = $1"
echo "Command-line argument #2 = $2"
echo "Command-line argument #3 = $3"


set `uname -a` # 把`uname -a`的命令输出设置
               # 为新的位置参数.

echo $_        # unknown(译者注: 这要看你的uname -a输出了,
#这句打印出的就是输出的最后一个单词.)
# 在脚本中设置标志.

echo "Positional parameters after  set \`uname -a\` :"
# $1, $2, $3, 等等. 这些位置参数将被重新初始化为`uname -a`的结果
echo "Field #1 of 'uname -a' = $1"
echo "Field #2 of 'uname -a' = $2"
echo "Field #3 of 'uname -a' = $3"
echo ---
echo $_        # ---
echo

exit 0
结果:
root@ubuntu:~/resource/shell-study/0615-2013# uname -a
Linux ubuntu 2.6.32-21-generic #32-Ubuntu SMP Fri Apr 16 08:10:02 UTC 2010 i686 GNU/Linux
root@ubuntu:~/resource/shell-study/0615-2013# ./test5.sh 

Positional parameters before  set `uname -a` :
Command-line argument #1 = 
Command-line argument #2 = 
Command-line argument #3 = 
GNU/Linux
Positional parameters after  set `uname -a` :
Field #1 of 'uname -a' = Linux
Field #2 of 'uname -a' = ubuntu
Field #3 of 'uname -a' = 2.6.32-21-generic
---
---

root@ubuntu:~/resource/shell-study/0615-2013#

root@ubuntu:~/resource/shell-study/0615-2013# ./test5.sh one two three 

Positional parameters before  set `uname -a` :
Command-line argument #1 = one
Command-line argument #2 = two
Command-line argument #3 = three
GNU/Linux
Positional parameters after  set `uname -a` :
Field #1 of 'uname -a' = Linux
Field #2 of 'uname -a' = ubuntu
Field #3 of 'uname -a' = 2.6.32-21-generic
---
---

root@ubuntu:~/resource/shell-study/0615-2013# 
一个反转位置参数的实例

#!/bin/bash

set a\ b c d\ e;
#     ^      ^     转义的空格
#       ^ ^        未转义的空格
echo "old IFS=$IFS"
OIFS=$IFS; IFS=:;
#              ^   保存旧的IFS, 然后设置新的IFS.
echo "new IFS=$IFS"
echo

until [ $# -eq 0 ]
do          #      步进位置参数.
  echo "### k0 = "$k""     # 步进之前
  k=$1:$k;  #      将每个位置参数都附加在循环变量的后边.
#     ^
  echo "### k = "$k""      # 步进之后
  echo
  shift;
done

set $k  #  设置一个新的位置参数.
echo -
echo $# #  察看位置参数的个数.
echo -
echo

for i   #  省略 "in list" 结构,
        #+ 为位置参数设置变量 -- i --.
do
  echo $i  # 显示新的位置参数.
done

IFS=$OIFS  # 恢复 IFS.

exit 0
结果:
root@ubuntu:~/resource/shell-study/0615-2013# chmod +x test6.sh 
root@ubuntu:~/resource/shell-study/0615-2013# ./test6.sh 
old IFS= 	

new IFS=:

### k0 = 
### k = a b

### k0 = a b
### k = c a b

### k0 = c a b
### k = d e c a b

-
3
-

d e
c
a b
root@ubuntu:~/resource/shell-study/0615-2013# 
不使用任何选项或参数来调用set命令的话, 将会列出所有的环境变量和其他所有的已经初始化过的变量

root@ubuntu:~/resource/shell-study/0615-2013# set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="1" [2]="5" [3]="1" [4]="release" [5]="i486-pc-linux-gnu")
BASH_VERSION='4.1.5(1)-release'
CLASSPATH=.:/usr/lib/jvm/java/jdk1.7.0_13/lib
COLORTERM=gnome-terminal
COLUMNS=85
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-NifSM3iDlO,guid=9ab993acd7e0b2bbecd0340551821d2e
DEFAULTS_PATH=/usr/share/gconf/gnome.default.path
DESKTOP_SESSION=gnome
DIRSTACK=()
DISPLAY=:0.0
EUID=0
GDMSESSION=gnome
GDM_KEYBOARD_LAYOUT=us
GDM_LANG=en_US.UTF-8
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
GNOME_KEYRING_CONTROL=/tmp/keyring-0pB4Zz
GNOME_KEYRING_PID=1726
GROUPS=()
GTK_MODULES=canberra-gtk-module
HISTCONTROL=ignoredups:ignorespace
HISTFILE=/root/.bash_history
HISTFILESIZE=2000
HISTSIZE=1000
HOME=/root
HOSTNAME=ubuntu
HOSTTYPE=i486
IFS=$' \t\n'
JAVA_HOME=/usr/lib/jvm/java/jdk1.7.0_13
LANG=en_US.UTF-8
LESSCLOSE='/usr/bin/lesspipe %s %s'
LESSOPEN='| /usr/bin/lesspipe %s'
LINES=20
LOGNAME=root
LS_COLORS='rs=0:di=01;34:ln=01;36:hl=44;37:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:'
MACHTYPE=i486-pc-linux-gnu
MAILCHECK=60
MANDATORY_PATH=/usr/share/gconf/gnome.mandatory.path
OLDPWD=/root/resource/shell-study
OPTERR=1
OPTIND=1
ORBIT_SOCKETDIR=/tmp/orbit-root
OSTYPE=linux-gnu
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/lib/jvm/java/jdk1.7.0_13/bin:/opt/FriendlyARM/toolschain/4.4.3/bin
PIPESTATUS=([0]="0")
PPID=2090
PS1='\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
PS2='> '
PS4='+ '
PWD=/root/resource/shell-study/0615-2013
SESSION_MANAGER=local/ubuntu:@/tmp/.ICE-unix/1744,unix/ubuntu:/tmp/.ICE-unix/1744
SHELL=/bin/bash
SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
SHLVL=1
SPEECHD_PORT=6560
SSH_AGENT_PID=1779
SSH_AUTH_SOCK=/tmp/keyring-0pB4Zz/ssh
TERM=xterm
UID=0
USER=root
USERNAME=root
WINDOWID=59004342
XAUTHORITY=/var/run/gdm/auth-for-root-cUTmoG/database
XDG_CONFIG_DIRS=/etc/xdg/xdg-gnome:/etc/xdg
XDG_DATA_DIRS=/usr/share/gnome:/usr/local/share/:/usr/share/
XDG_SESSION_COOKIE=e2701cc9fa08772c6d472e6450b8b925-1367481646.513094-1041457640
_=three
process=xterm
show_process='eval ps ax | grep xterm'
command_not_found_handle () 
{ 
    if [ -x /usr/lib/command-not-found ]; then
        /usr/bin/python /usr/lib/command-not-found -- $1;
        return $?;
    else
        if [ -x /usr/share/command-not-found ]; then
            /usr/bin/python /usr/share/command-not-found -- $1;
            return $?;
        else
            return 127;
        fi;
    fi
}
root@ubuntu:~/resource/shell-study/0615-2013# 
如果使用参数--来调用set命令的话, 将会明确的分配位置参数. 如果--选项后边没有跟变量名的话, 那么结果就使得所有位置参数都被unsets了.

一个重新分配位置参数的实例

#!/bin/bash

variable="one two three four five"

set -- $variable
# 将位置参数的内容设为变量"$variable"的内容.

first_param=$1
second_param=$2
shift; shift        # 将最前面的两个位置参数移除.
remaining_params="$*"

echo
echo "first parameter = $first_param"             # one
echo "second parameter = $second_param"           # two
echo "remaining parameters = $remaining_params"   # three four five

echo; echo

# 再来一次.
set -- $variable
first_param=$1
second_param=$2
echo "first parameter = $first_param"             # one
echo "second parameter = $second_param"           # two

# ======================================================

set --
# 如果没指定变量,那么将会unset所有的位置参数.

first_param=$1
second_param=$2
echo "first parameter = $first_param"             # (null value)
echo "second parameter = $second_param"           # (null value)

exit 0
结果:
root@ubuntu:~/resource/shell-study/0615-2013# chmod +x test7.sh 
root@ubuntu:~/resource/shell-study/0615-2013# ./test7.sh 

first parameter = one
second parameter = two
remaining parameters = three four five


first parameter = one
second parameter = two
first parameter = 
second parameter = 
root@ubuntu:~/resource/shell-study/0615-2013# 

unset

unset命令用来删除一个shell变量, 这个命令的效果就是把这个变量设为null. 注意: 这个命令对位置参数无效.
bash$ unset PATH
bash$ echo $PATH

bash$ 
"Unset"一个变量的实例
#!/bin/bash
# unset.sh: Unset 一个变量.

variable=hello                       # 初始化.
echo "variable = $variable"

unset variable                       # Unset.
                                     # 与 variable= 效果相同.
echo "(unset) variable = $variable"  # $variable 设为 null.

exit 0
结果:
root@ubuntu:~/resource/shell-study/0615-2013# chmod +x test8.sh 
root@ubuntu:~/resource/shell-study/0615-2013# ./test8.sh 
variable = hello
(unset) variable = 
root@ubuntu:~/resource/shell-study/0615-2013# 

export

export命令将会使得被export的变量在所运行脚本(或shell)的所有子进程中都可用. 不幸的是, 没有办法将变量export到父进程中, 这里所指的父进程就是调用这个脚本的脚本或shell. 关于export命令的一个重要的用法就是使用在启动文件中, 启动文件用来初始化和设置环境变量, 这样, 用户进程才能够访问环境变量.

declare, typeset

declare和typeset命令被用来指定或限制变量的属性.

readonly

与declare -r作用相同, 设置变量的只读属性, 或者可以认为这个变量就是一个常量. 设置了这种属性之后, 如果你还要修改它, 那么将会得到一个错误信息. 这种情况与C语言中的const常量类型是相同的.

getopts

可以说这个命令是分析传递到脚本中命令行参数的最强力的工具. 这个命令与外部命令getopt, 还有C语言中的库函数getopt 的作用是相同的. 它允许传递和连接多个选项到脚本中, 并且能够分配多个参数到脚本中(比如: scriptname -abc -e /usr/local).

getopts结构使用两个隐含变量. $OPTIND是参数指针(选项索引) 和$OPTARG(选项参数)(可选的)可以在选项后边附加一个参数. 在声明标签中, 选项名后边的冒号用来提示这个选项名已经分配了一个参数.

getopts结构通常都组成一组放在一个while循环中, 循环过程中每次处理一个选项和参数, 然后增加隐含变量$OPTIND的值, 再进行下一次的处理.

1、通过命令行传递到脚本中的参数前边必须加上一个减号(-). -是一个前缀, 这样getopts命令把这个参数看作为一个选项. 事实上, getopts不会处理不带-前缀的参数, 如果第一个参数就没有-, 那么将会结束选项的处理.

2、getopts的while循环模板与标准的while循环模板有些不同, 没有标准循环中的中括号[]判断条件.

3、getopts结构将会取代外部命令getopt.

先到这里了,O(∩_∩)O~

我的专栏地址:http://blog.csdn.net/column/details/shell-daily-study.html

待续。。。。

你可能感兴趣的:(shell)