應用場景:
我們在工作中經常會有要定時輸出一些文件到磁盤上用作離線詞表或者數據的冷備,但是如果這些數據不定期清理的話,則會對我們的磁盤造成巨大的浪費,人工手動清理的話,總是會有遺忘的時候,所以此刻就需要有一個自動清理的腳本。
假設現場:我們有一個定時生成詞表到指定目錄的程序,輸出的目錄名和詞表前綴相同,且在生成詞表的同時,會將詞表名和對應的md5輸出到詞表同目錄的list文件中用在校驗。
任務:1.清理7天的詞表文件 2.同時清理對應list中的數據
腳本內容
話不多說,先直接上腳本:
#只保留7天的數據 REMAIN_DAYS=7 HOST="root@10.10.123.251" PASS="123456" DICT_NAME="my_dictionary" DICT_DIR="/export/data/${DICT_NAME}" function clean() { local del_days=${REMAIN_DAYS} del_days=$(( del_days-1 )) echo "begin clean..." #刪除過期文件 echo "ssh -t \"${HOST}\" \"find ${DICT_DIR} -mtime +${del_days} | xargs rm -rf {}\"" sshpass -p "${PASS}" ssh -t "${HOST}" "find ${DICT_DIR} -mtime +${del_days} | xargs rm -rf {}" #更新list:獲取文件數和list行數,若list行數大於文件數,則去除過去的差值行數 local file_nums=`sshpass -p "${PASS}" ssh -t "${HOST}" "find ${DICT_DIR} -name \"${DICT_NAME}-*\" | wc -l"` local list_nums=`sshpass -p "${PASS}" ssh -t "${HOST}" "cat ${DICT_DIR}/list | wc -l"` local file_nums_length=$(( ${#file_nums} )) local list_nums_length=$(( ${#list_nums} )) let file_nums=0+${file_nums:0:${file_nums_length}} let list_nums=0+${list_nums:0:${list_nums_length}} local minus_num=$(( list_nums - file_nums )) echo "file_nums:$file_nums, list_nums:$list_nums, minus_num:$minus_num" if [ $minus_num -gt 0 ]; then echo "delete list: 1,${minus_num}d" sshpass -p "${PASS}" ssh -t "${HOST}" "sed -i '1,${minus_num}d' ${DICT_DIR}/list" fi echo "clean finished..." }
其中不少人可能會奇怪為什么會有這一段代碼:
local file_nums_length=$(( ${#file_nums} )) local list_nums_length=$(( ${#list_nums} )) let file_nums=0+${file_nums:0:${file_nums_length}} let list_nums=0+${list_nums:0:${list_nums_length}}
主要是因為剛開始沒加這一段兒的時候一直報錯")syntax error: invalid arithmetic operator (error token is",查了一下文檔,說是因為用字符串做了數值計算邏輯導致的,然后想用這種方式把字符串轉成數值。但是其實至今不知道那個是為什么報錯,有知道的大佬也請解惑呀,感謝了。
下面也會對我這個腳本的知識點作一個具體梳理。
find -mtime +N/-N/N 的時間算法:
在unix或linux環境中經常會用到find -mtime這樣的寫法來找某某時間點之前的文件,至於如何寫find -mtime +N/-N/N,原來並不是很清楚,今天找了些資料看看,畫下了這個圖,以便理解和記憶:
從圖上可以看出,以當前時間點開始算起,+表示往左,從該時間點開始再繼續往更早推,可以稱作xx以外;-表示往右,從該時間點算起往后的時間推,可以稱作xx以內;沒有加減號表示據此此前第N天。因此:
我們來看下面這個例子:
我當前的時間2011年3月1日22:31,我有如下的文件:
E:\testpath>ls -l total 0 -rwxrwxrwa 1 Administrator None 0 Feb 25 22:37 111.txt -rwxrwxrwa 1 Administrator None 0 Feb 26 22:38 222.txt -rwxrwxrwa 1 Administrator None 0 Feb 27 22:38 333.txt -rwxrwxrwa 1 Administrator None 0 Feb 28 22:01 444.txt -rwxrwxrwa 1 Administrator None 0 Feb 28 22:30 555.txt -rwxrwxrwa 1 Administrator None 0 Mar 1 22:31 666.txt<--當前時間的文件 -rwxrwxrwa 1 Administrator None 0 Mar 2 2011 777.txt E:\testpath>
-mtime +2,表示2天以外的,即從距離當前時間(2011-03-01 22:31)的2天前開始算起,往更早的時間推移。因此,距離當前時間的2天為:2011-02-27 22:31,在此前的文件,會被選出來。
E:\testpath>find ./ -mtime +2 ./111.txt ./222.txt
-mtime +1,表示1天以外的,即從距當前時間的1天前算起,往更早的時間推移。因此2011-02-28 22:31前的文件屬於該結果,2011-02-28 22:31后的文件不屬於該結果:
E:\testpath>find ./ -mtime +1 ./111.txt ./222.txt ./333.txt ./444.txt ./555.txt
-mtime 2, 距離當前時間第2天的文件,當前時間為2011-03-01 22:31,往前推2天為2011-02-27 22:31,因此以此為時間點,24小時之內的時間為2011-02-27 22:31~2011-02-28 22:31,因此這段時間內的文件會被選中出來:
E:\testpath>find ./ -mtime 2 ./333.txt ./444.txt ./555.txt
-mtime 1, 距離當前時間第1天的文件,當前時間為2011-03-01 22:31,往前推1天為2011-02-28 22:31,因此以此為時間點,24小時之內的時間為2011-02-28 22:31~2011-03-01 22:31,因此這段時間內的文件會被選中出來:
E:\testpath>find ./ -mtime 1 ./666.txt
-mtime -1 表示1天以內的,從距當前時間的1天為2011-02-28 22:31,往右推移:
E:\testpath>find ./ -mtime -1 ./ ./666.txt ./777.txt
-mtime -2 表示2天以內的,從距當前時間的2天為2011-02-27 22:31開始,往右推移:
E:\testpath>find ./ -mtime -2 ./ ./333.txt ./444.txt ./555.txt ./666.txt ./777.txt
find -mtime命令參數理解:
find . -mtime N
實際上你應該這樣理解..
N * 24
+1 內表示 1 * 24 +24小時以外..
+0 才表示 0 * 24 +24小時以外
1 表示 1*24 + 24 到 24 之間..
0 表示 0*24 + 24 到 0 之間..
-1 表示 0*24 +24 內,甚至為未來時間...
記住0也是自然數....
Linux xargs命令
xargs 是給命令傳遞參數的一個過濾器,也是組合多個命令的一個工具。
xargs 可以將管道或標准輸入(stdin)數據轉換成命令行參數,也能夠從文件的輸出中讀取數據。
xargs 也可以將單行或多行文本輸入轉換為其他格式,例如多行變單行,單行變多行。
xargs 默認的命令是 echo,這意味着通過管道傳遞給 xargs 的輸入將會包含換行和空白,不過通過 xargs 的處理,換行和空白將被空格取代。
xargs 是一個強有力的命令,它能夠捕獲一個命令的輸出,然后傳遞給另外一個命令。
參數:
- -a file 從文件中讀入作為sdtin
- -e flag ,注意有的時候可能會是-E,flag必須是一個以空格分隔的標志,當xargs分析到含有flag這個標志的時候就停止。
- -p 當每次執行一個argument的時候詢問一次用戶。
- -n num 后面加次數,表示命令在執行的時候一次用的argument的個數,默認是用所有的。
- -t 表示先打印命令,然后再執行。
- -i 或者是-I,這得看linux支持了,將xargs的每項名稱,一般是一行一行賦值給 {},可以用 {} 代替。
- -r no-run-if-empty 當xargs的輸入為空的時候則停止xargs,不用再去執行了。
- -s num 命令行的最大字符數,指的是 xargs 后面那個命令的最大命令行字符數。
- -L num 從標准輸入一次讀取 num 行送給 command 命令。
- -l 同 -L。
- -d delim 分隔符,默認的xargs分隔符是回車,argument的分隔符是空格,這里修改的是xargs的分隔符。
- -x exit的意思,主要是配合-s使用。。
- -P 修改最大的進程數,默認是1,為0時候為as many as it can ,這個例子我沒有想到,應該平時都用不到的吧。
實例
xargs 用作替換工具,讀取輸入數據重新格式化后輸出。
定義一個測試文件,內有多行文本數據:
# cat test.txt a b c d e f g h i j k l m n o p q r s t u v w x y z
多行輸入單行輸出:
# cat test.txt | xargs a b c d e f g h i j k l m n o p q r s t u v w x y z
-n 選項多行輸出:
# cat test.txt | xargs -n3 a b c d e f g h i j k l m n o p q r s t u v w x y z
-d 選項可以自定義一個定界符:
# echo "nameXnameXnameXname" | xargs -dX name name name name
結合 -n 選項使用:
# echo "nameXnameXnameXname" | xargs -dX -n2 name name name name
讀取 stdin,將格式化后的參數傳遞給命令
假設一個命令為 sk.sh 和一個保存參數的文件 arg.txt:
#!/bin/bash #sk.sh命令內容,打印出所有參數。 echo $*
arg.txt文件內容:
# cat arg.txt aaa bbb ccc
xargs 的一個選項 -I,使用 -I 指定一個替換字符串 {},這個字符串在 xargs 擴展時會被替換掉,當 -I 與 xargs 結合使用,每一個參數命令都會被執行一次:
# cat arg.txt | xargs -I {} ./sk.sh -p {} -l -p aaa -l -p bbb -l -p ccc -l
復制所有圖片文件到 /data/images 目錄下:
ls *.jpg | xargs -n1 -I {} cp {} /data/images
xargs 結合 find 使用
用 rm 刪除太多的文件時候,可能得到一個錯誤信息:/bin/rm Argument list too long. 用 xargs 去避免這個問題:
find . -type f -name "*.log" -print0 | xargs -0 rm -f
xargs -0 將 \0 作為定界符。
統計一個源代碼目錄中所有 php 文件的行數:
find . -type f -name "*.php" -print0 | xargs -0 wc -l
查找所有的 jpg 文件,並且壓縮它們:
find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz
xargs 其他應用
假如你有一個文件包含了很多你希望下載的 URL,你能夠使用 xargs下載所有鏈接:
# cat url-list.txt | xargs wget -c
轉載請注明出處:https://www.cnblogs.com/fnlingnzb-learner/p/13031967.html