shell 封装一些实用的函数

#函数是功能是以自定义的方式把命令行的选项和参数拆分成数组。引号中的内容在计算位置时会当作一个整体。
#parse.option <default> <retain> "$@"
#default 默认选项,如果为空请用  -  占位
#retain 保留最后几位做为参数
#"$@" 这个变量表示参数列表
# 如:parse.option '-de -f'  2  "$@"

function parse.option(){ local defalut="$1" local option="" local retain="$2" local args="" shift 2; local arr=( "$@" ) local length=${#arr[@]} for i in "${!arr[@]}"; do [ -n "`echo ${arr[$i]} | grep -P 's*w+s+s*'`" ] && arr[$i]=""${arr[$i]}"" done [ $length -eq "$retain" ] && args=${arr[@]:$length - $retain} [ $length -gt "$retain" ] && { option=${arr[@]:0:$length - $retain}; args=${arr[@]:$length - $retain}; } [ -z "$option" -a "$defalut" != '-' ] && option="$defalut" echo "([0]='$option' [1]='$args')" }

我想扩展一个 ln 命令,因为它不够方便,非要写绝对路径。我想让相对路径也创建。

function ln(){
declare
-A all=`parse '-isv' 2 "$@"` set -- ${all[1]} local target=$1 [ ${target:0:1} != '/' ] && target="`pwd`/$target" sudo /usr/bin/ln ${all[0]} $target $2
}

这里用到了 parse.option "$*" 2 '-is'  也就是说,前面都是选项,只有最后两位是参数,默认选项是 -is  选项我不管,我只处理路径参数

如果目标路径不是以 / 开头,那就在路径前面加上当前路径,组成绝对路径。这样既扩展了 ln 的功能,同时也没有把选项写死。

下面还有一些常用函数。

function start(){

    case "$1" in
        'php')      sudo php-fpm;;
        'nginx')    sudo nginx;;
        'redis')    redis-server;;
        :*)         
                    local item="${@#:}"
                    [ "$@" == ":all" ] && item="$(docker ps -q -f status=exited)"
                    [ -n "$item" ] && docker start $item
        ;;   
        '')         start docker;;
        'web')      start php && start nginx;;
        *)          sudo service $1 start;;
    esac
}

function stop(){

    case "$1" in
        'php')      sudo pkill -9 php-fpm;;
        'nginx')    sudo nginx -s stop;;
        'web')      stop php && stop nginx;;
        'redis')    redis-cli shutdown;;
        -*)         sudo pkill -9 ${1#-};;
        :*)         
                    local item="${@#:}"
                    [ "$@" == ":all" ] && item="$(docker ps -q)"
                    [ -n "$item" ] && docker stop $item
        ;;
        *)          sudo service $1 stop;;
    esac
}


#批量将文件链接到 bin 目录,如果参数是一个目录,则链接目录中的所有文件
function tobin(){

    [ $# == 1 -a  -d "$1"  ]  && { cd $1;  set -- `ls $1`;  }
    for item in "$@"; do
        [  ${item:0:1} != '/'  ] && item="`pwd`/$item"
        [  -f "$item" ] && sudo ln -fs $item /usr/local/bin && echo "$item"
    done

}

function tosbin(){

    [ $# == 1 -a  -d "$1"  ]  &&  { cd $1; set -- `ls $1`;  }
    for item in "$@"; do
        [  ${item:0:1} != '/'  ] && item="`pwd`/$item"
        [  -f "$item" ] && sudo ln -fs $item /usr/local/sbin && echo "$item"
    done

}


#打开文件或目录
#可以打开 docker 容器中的文件,如: open :container /tmp/test.txt  注:参数要冒号开头
#会把容器中的文件复制到 /tmp/<container>/ 目录中,如果复制为成功,则在该目录新建。
#可以再结合一个 push :container /tmp/test.txt 就会找到  /tmp/<container>/test.txt 并复制到容器中
#如果没有参数,表示打开当前目录
#由于我是用的 WSL 打开当前目录的命令 explorer.exe . 请换成 xdg-open 命令

function open(){

    option="$1"
    case "$option" in
        '-source')  code /etc/apt/sources.list;;
        '-profile') code /etc/profile;;
        '-bashrc')  code /etc/bash.bashrc;;
        :*)
                    local con="${option#:}"
                    local file="/tmp/$con`basename $2`"
                    mkfdir $file
                    docker cp $con:$2 $file 2>/dev/null
                    open $file
        ;;
        '')         explorer.exe .;; #xdg-open $PWD;;
        *)

            mime=`file --mime-type $option | awk '{print $2}'`
            #如果是符号链接
            if [ $mime == 'inode/symlink' ];then
                option=`readlink -e $option`
                mime=`file --mime-type $option | awk '{print $2}'`
            fi

            if [ -n "`echo $mime | grep -E '^(text/|inode/x-empty|application/json)'`" ];then
                #用编辑器打开
                code $option

            elif [ "$mime" = 'inode/directory' ];then
                cd $option && explorer.exe .
                #xdg-open $option

            elif [ "$mime" != 'cannot' ];then
                #默认方式打开
                color red "文件类型:$mime"
                explorer.exe $option
                #xdg-open $option
                
            else
                color red "新建: $option"
                [ ! -w . ] && sudo touch $option
                code $option
            fi

        ;;

    esac

}


#可以推送 git
#可以结合上面 open 可以再把文件推送到容器
function push(){

    option="$1"
    case "$option" in
        :*)     local conter="${option#:}"; docker cp /tmp/$conter/`basename $2` $conter:$2 || { echo "上传失败"; return 1; };;   
        '')     push .;;
        *)      git add $@ && git commit -m '日常更新' && git push;;
    esac

}

#文件重命令
#第二个参数只是单纯表示新名字,如:rename /home/old.txt new.txt
function rename(){
    sudo mv $1 `dirname $1`/$2
}

#类似于 whereis 命令,但列出内容更详细
function where(){

    local name="$1"
    [ -n "`which $name`" ]  && { color red "当前命令:"; which $name; } 
    [ -n "`type -a $name 2>/dev/null`" ] && { color red "命令列表:"; type -a $name; }
    [ "`whereis $name`" != "$name:" ] && { color red "目录列表:"; whereis $name; } || color red "$name 不存在"

}

#综合了 apt install 和 dpkg -i 安装软件
#如果不带任何参数,则进入查找安装过程
#如:install 回车,输入 mysql,会列出包名,输入要安装的包名或输入 exit 退出

function install(){

    if [ $# == 0 ];then

        [ -z `which sudo` ] && apt install -y sudo
        local software=""
        until [ "$software" == 'exit' ]
        do
            
            echo -en "33[31m查找: 33[0m"
            read software

            [ "$software" == 'exit' -o -z "$software" ] && break
        
            apt list "$software*";
            apt list "lib{$software}*";
            
            echo -en "33[31m安装: 33[0m"
            read software

            if [ "$software" == 'next' -o -z "$software" ];then
                continue
            elif [ "$software" == 'exit' ];then
                break
            fi

            sudo apt install -y $software && echo $software >> ~/.install.log

        done

    else

        local ext="${1##*.}"
        case "$ext" in
            'deb')  sudo dpkg -i $1;;
            'rpm')  sudo rpm -i $1;;
            *) 
                if [ -n "`which apt`" ];then
                    sudo apt install -y $1 && echo $1 >> ~/install.log
                elif [ -n "`which yum`" ];then
                    sudo yum install -y $1 && echo $1 >> ~/install.log
                fi
            ;;
        esac

    fi

}

  

原文地址:https://www.cnblogs.com/zbseoag/p/14241017.html