初試Shell指令碼

2021-09-24 08:04:18 字數 4162 閱讀 4091

#

!/usr/bin/env bash

#created by vanch at 2018/9/20

printhelp()

#如果沒輸入引數,就列印幫助資訊

if [ $# -eq 0 ]; then

printhelp

exit 0fi#

把長選項轉到短選項

for arg in "$@"; do

shift

case "$arg" in

"--help") set -- "$@" "-h" ;;

"--version") set -- "$@" "-v" ;;

"--list") set -- "$@" "-l" ;;

*) set -- "$@" "$arg"

esac

done

#獲取短選項

optind=1

prints=false;

while getopts "dmksahvl" opt; do

case $opt in

h) #輸入為help,就列印幫助資訊

printhelp

exit 0;;

l) #支援單獨獲取支援檔案字尾列表

echo "supported file types: zip tar tar.gz tar.bz2"

exit 0;;

v) #支援查詢版本號

echo "1.0.0"

exit 0;;

s) #過濾socket

prints=true;;

esac

done

#獲得壓縮包位址

file=$

#如果不存在就退出

if [ ! -f "$file" ]; then

echo "file not exist!"

exit 0;

fi #

獲取壓縮字尾

filename=`basename $file`

suffix=$

#判斷檔案型別

support=('tar','tar.gz','tar.bz2','zip')

if [ -z `echo "$" | grep -w "$suffix"` ] ; then

echo "file type not support!"

exit 0; fi#

拼接資料夾位址

filedir=$(dirname $file)/$

if [ -d $filedir ]; then

rm -rf $filedir

fimkdir $filedir

cd $filedir

#解壓檔案

case $suffix in

'tar')

eval "tar xvf $file > /dev/null 2>&1";;

'tar.gz')

eval "tar zxvf $file > /dev/null 2>&1";;

'tar.bz2')

eval "tar jxvf $file > /dev/null 2>&1";;

'zip')

eval "unzip -o $file > /dev/null 2>&1";;

esac

echo 'uncompass success!'

#獲取日誌列表,按排序合併到乙個日誌

mergefile=./merge.log

logcount=0

#搜尋com開頭的日誌,按日期排序,用?臨時代替空格

for logname in `ls | grep 'com' | sort -n | tr " " "?"`; do

logname=$

cat ./"$logname" >> $mergefile

((logcount++))

done

#不存在日誌就打斷

if [ $logcount -eq 0 ]; then

echo "log not exist!"

exit

fiecho 'merge success!'

#列印socket

if [ $prints = true ]; then

cat $mergefile | grep -i 'socket' >> ./socket.log

echo 'filter socket'

fi複製**

查詢了很多資料後寫完了這個指令碼,基本滿足了我的需求,下面總結一下怎麼解決遇到的問題。

一開始學指令碼時,書上都說#! /bin/bash,但是看專案中大神寫的指令碼,都是#!/usr/bin/env bash,有什麼區別呢?

指令碼用env啟動的原因,是因為指令碼直譯器在linux中可能被安裝於不同的目錄,env可以在系統的path目錄中查詢。 同時,env還規定一些系統環境變數。

不同的系統,直譯器的路徑可能也不同,所以使用絕對路徑是比較危險的方式。通過從環境中查詢,可以保證相容性。

開發中我們經常用到命令,這些命令一般都配合選項達到不同的效果,比如最常用的ls -al,通過-a來指定結果包含隱藏檔案,通過-l達到列表顯示的效果。

通過查詢相關資料,我發現獲取選項普遍的做法是使用getopts命令,但是這個方法只能獲取-h這種短選項,對於--help長選項就不行。

第一種辦法是換成getopt命令,但是並不是每個系統都支援這個命令。具體使用和getopts類似,比如getopt -o ab:c -l a-long:b-long

第二種方法是把支援的長命令轉成短命令,我使用的就是這種方式,相對來說比較容易理解,且case寫的比較統一。通過shift取出引數,再set --的方式重寫,最後optind=1把指標指回第乙個選項。

按需求需要判斷字尾名來解壓,那麼就需要判斷tar.gz之類的問題。同時,如果傳入的檔案目錄是隱藏目錄,也會造成一定的障礙。我們假設傳入檔案路徑為/a/.b/c.tar.gz

如果按照$來擷取,那麼只能拿到gz。 如果按照$來擷取,拿到的又是b/c.tar.gz。那怎麼辦呢?

好在有dirname可以直接獲取檔案路徑,basename拿到檔名,單獨對檔名進行$就可以拿到tar.gz了。

執行解壓命令時,會列印解壓步驟,一般來說也需要顯示,那如果我們不想要列印出來呢?有乙個辦法就是在命令之後加上> /dev/null 2>&1

/dev/null :代表空裝置檔案

> :代表重定向到**,例如:echo "123" > /home/123.txt

1 :表示stdout標準輸出,系統預設值是1,所以">/dev/null"等同於"1>/dev/null"

2 :表示stderr標準錯誤

& :表示等同於的意思,2>&1,表示2的輸出重定向等同於1

所以含義就是把命令輸出結果和錯誤輸出重定向,使得輸出不在當前螢幕顯示,由於null比較特殊,向這個檔案輸入等於進入黑洞,因此達到效果。

使用ls | grep的方式來過濾結果獲取檔名陣列的最大問題是,如果檔名包含空格,那麼前後會被分割成兩個單元,導致處理比較困難。

比較討巧的方法是臨時用特殊符號代替空格,在使用時再替換回來。這種方法不會改變檔名,也不用寫複雜的陣列合併,比較符合簡單的設計。

tr " " "?"

$複製**

通過這次簡單的指令碼實驗,對shell有了新的認識,及時記錄遇到的問題,相信下次會更有印象。使用指令碼,可以讓工作更有效率,相信以後也會越用越多。

Shell指令碼(三) Shell指令碼入門

1 指令碼格式 指令碼以 bin bash開頭 指定解析器 2 第乙個shell指令碼 helloworld 1 需求 建立乙個shell指令碼,輸出helloworld 2 案例實操 atguigu hadoop101 datas touch helloworld.sh atguigu hadoo...

Shell指令碼和shell

1.shell script,shell指令碼與windows dos下的批處理相似,也就是用各類命令預先放入到乙個檔案中,方便一次性執行的乙個程式檔案,主要是方便管理員進行設定或者管理用的。但是它比windows下的批處理更強大,比用其他程式設計程式編輯的程式效率更高,畢竟它使用了linux un...

shell 執行shell指令碼

bin bash echo hello world 是乙個約定的標記,它告訴系統這個指令碼需要什麼直譯器來執行,即使用哪一種 shell。echo 命令用於向視窗輸出文字。1 作為可執行程式 chmod x test.sh 使指令碼具有執行許可權 test.sh 執行指令碼注意,一定要寫成 test...