天天看點

《linux Shell 腳本攻略》進階學習(第二部分)

第三章 以檔案之名

生成任意大小的檔案

$ dd if=/dev/zero of=junk.data bs=1M count=1

記錄了1+0 的讀入

記錄了1+0 的寫出

1048576位元組(1.0 MB)已複制,0.735955 秒,1.4 MB/秒

查找并删除重複檔案

條件:删除那些雖然名字不同但内容一模一樣的檔案

通過檔案内容來識别他們,校驗和是依據檔案内容來計算的,内容相同的檔案自然就生成想通的校驗和

通過比較校驗和來删除重複檔案

書本代碼有誤,補充如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

<code>#!/bin/bash</code>

<code>ls</code> <code>-lS | </code><code>awk</code> <code>'BEGIN{</code>

<code>getline;getline;</code>

<code>name1=$9;</code>

<code>size=$5</code>

<code>}</code>

<code>{</code>

<code>name2=$9;</code>

<code>if</code> <code>(size==$5)</code>

<code>"md5sum $name1"</code>  <code>| getline;csum1=$1;</code>

<code>"md5sum $name2"</code>  <code>| getline;csum2=$1;</code>

<code>if</code> <code>(csum1==csum2)</code>

<code>print name1;</code>

<code>print name2;</code>

<code>};</code>

<code>size=$5;</code>

<code>name1=name2;</code>

<code>}' | </code><code>sort</code> <code>-u &gt; duplicate_files</code>

<code>cat</code> <code>duplicate_files | </code><code>xargs</code> <code>-I {} md5sum {} | </code><code>sort</code> <code>| </code><code>uniq</code> <code>-w 32 | </code><code>awk</code> <code>'{ print $2 }'</code> <code>| </code><code>sort</code> <code>-u &gt; duplicate_sample</code>

<code>echo</code> <code>Removing..</code>

<code>comm</code> <code>duplicate_files duplicate_sample -2 -3 | </code><code>tee</code> <code>/dev/stderr</code> <code>| </code><code>xargs</code> <code>rm</code> <code>-f</code>

<code>echo</code> <code>Removed duplicates files successfully.</code>

<code>rm</code> <code>duplicate_sample duplicate_files</code>

以不同的使用者運作可執行檔案

原理:有一個叫做setuid的特殊檔案權限,它允許其他使用者以檔案所有者的身份來執行檔案

chown root.root execu_file

chown +s execu_file

./execu_file

這個檔案事實上每次以超級使用者來運作

setuid的使用不是無限制的,它隻能應用在linux ELFG格式二進制檔案上,二不能用于腳本

建立檔案不可修改

限制:一旦檔案呗設定為不可修改,任意使用者包括超級使用者都不能删除檔案,除非其不可修改的屬性被移除

通過檢視/etc/mtab檔案,很容易找出所有挂載分區的檔案系統類型

cat /etc/mtab

/dev/sda1 / ext4 rw,errors=remount-ro 0 0

proc /proc proc rw,noexec,nosuid,nodev 0 0

sysfs /sys sysfs rw,noexec,nosuid,nodev 0 0

none /sys/fs/cgroup tmpfs rw 0 0

none /sys/fs/fuse/connections fusectl rw 0 0

none /sys/kernel/debug debugfs rw 0 0

none /sys/kernel/security securityfs rw 0 0

udev /dev devtmpfs rw,mode=0755 0 0

devpts /dev/pts devpts rw,noexec,nosuid,gid=5,mode=0620 0 0

tmpfs /run tmpfs rw,noexec,nosuid,size=10%,mode=0755 0 0

none /run/lock tmpfs rw,noexec,nosuid,nodev,size=5242880 0 0

none /run/shm tmpfs rw,nosuid,nodev 0 0

none /run/user tmpfs rw,noexec,nosuid,nodev,size=104857600,mode=0755 0 0

binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,noexec,nosuid,nodev 0 0

gvfsd-fuse /run/user/zhangjianlin/gvfs fuse.gvfsd-fuse rw,nosuid,nodev,user=zhangjianlin 0 0

可以用chattr将檔案設定為不可修改

實戰演練

将一個檔案設定為不可修改

chattr +i file

或者sudo chattr +i file

rm file出錯

移除不可修改的屬性

chattr -i file

修改檔案三個時間

touch -a 更檔案通路時間

touch -m 更改檔案内容修改時間

touch -d 時間戳

列舉檔案夾下的類型統計資訊

file -b filename

ASXII text

腳本如下

<code>if</code> <code>[ $</code><code># -ne 1 ];</code>

<code>then</code>

<code>    </code><code>echo</code> <code>$0 basepath;</code>

<code>    </code><code>echo</code>

<code>fi</code>

<code>path=$1</code>

<code>declare</code> <code>-A statarray</code>

<code>while</code> <code>read</code> <code>line;</code>

<code>do</code>

<code>    </code><code>ftype=`</code><code>file</code> <code>-b </code><code>"$line"</code><code>`</code>

<code>    </code><code>let</code> <code>statarray[</code><code>"$ftype"</code><code>]++;</code>

<code>    </code><code>done</code><code>&lt; &lt;(</code><code>find</code> <code>$path -</code><code>type</code> <code>f -print)</code>

<code>                                                                                                                                                                                             </code> 

<code>echo</code> <code>========</code><code>file</code> <code>types and counts==========</code>

<code>for</code> <code>ftype </code><code>in</code> <code>"${!statarray[@]}"</code><code>;</code>

<code>    </code><code>echo</code> <code>$ftype : ${statarray[</code><code>"$ftype"</code><code>]}</code>

<code>done</code>

結果

$ bash filestat.sh .

========file types and counts==========

Bourne-Again shell script, ASCII text executable : 2

empty : 2

原理

while read line

do

  echo $line

done&lt;A  

&lt;A寫在最後相當于給整個while do 語句加了一個限制條件,讀取檔案A裡每行至檔案尾結束

while read line&lt;A

   echo $line

done

&lt;A寫在前面,整個while do語句就沒有限制條件, 因為 read line&lt;A這個始終為真

表示 不停地  讀取A中的第一行,指派給參數line,然後列印參數line的值.

done&lt; &lt;(find $path -type f -print) 

&lt;(find $path -type f -print)  等同與檔案名。隻不過他用子程序輸出代替檔案名

${!statarray[@]} 用于傳回一個數組索引清單

第四章。讓文本飛

正規表達式入門

更多内容百度

比對一個ip位址

[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

grep搜尋文本

擴充内容

遞歸搜尋包含詞的檔案

grep "text" . -R -n #開發人員常用的指令

$ grep "bin" . -R -n 

./第三章:42:binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,noexec,nosuid,nodev 0 0

./第三章:66:#!/bin/bash

./second/mvsuffix.sh:1:#!/bin/bash

./second/mvfilename.sh:1:#a!/bin/bash

./touchlearnfiles.sh:1:#!/bin/bash

./第一章.txt:25:#!/bin/bash

./第一章.txt:36:#!/bin/bash

./第一章.txt:45:#!/bin/bash

./第一章.txt:71:#!/bin/bash

./第一章.txt:74:(cd /bin; ls);

./第一章.txt:97:#!/bin/bash

./第一章.txt:117:#!/bash/bin

./第一章.txt:133:line="root:x:0:0:root:root:/bin/bash"

./第一章.txt:178:#!/bin/bash

./first/password.sh:1:#!/bin/bash

./first/dealpasswd.sh:1:#!/bash/bin

./first/dealpasswd.sh:17:line="root:x:0:0:root:root:/bin/bash"

./first/IFSofdiv.sh:1:#!/bin/bash

./first/array_var.sh:1:#!/bin/bash

./first/cilldshell.sh:1:#!/bin/bash

./first/cilldshell.sh:4:(cd /bin; ls);

./first/delaysleep.sh:1:#!/bin/bash

./first/filetest.sh:1:#!/bin/bash

./第二章.txt:160:#a!/bin/bash

./第二章.txt:196:#!/bin/bash

./third/filestat.sh:1:#!/bin/bash

./third/remove_duplicates.sh:1:#!/bin/bash

在grep 搜尋中包括或排除檔案

隻在目錄中遞歸搜尋所有的.c .cpp檔案:

$ grep  "main()" . -r --include *.{c,cpp}

搜尋中排除所有的README檔案

$ grep  "main()" . -r --exclude "README"

對檔案中的行、單詞和字元進行疊代

實戰

疊代檔案中的每一行

while read line;

echo $line;

done &lt; file.txt

每一行的單詞

for word in $line

echo $word ;

疊代一個單詞中方的每一個字元

for ((i=0;i&lt;${#word};i++))

echo

${word:i:1};

${word:start_position:no_of_characters} 傳回變量word所包含的字元串中的一個字竄 :重要

cat touchlearnfiles.sh | (while read line; do echo $line; done)

結果:

#!/bin/bash

arrays=("一" "二" "三" "四" "五" "六" "七" "八" "九" "十")

arraynums=(first second third fourth fifth sixth seventh eighth ninth tenth)

read -p "please input the number of caption:" num;

touch "第${arrays[$num-1]}章.txt"

mkdir ${arraynums[$num-1]}

awk列印多列資料,并在列間插入指定的字元

$ ls -l | awk '{ print $1" : " $8 }' 

實戰演練:列印不同行或樣式之間的文本

列印從第M行到N行這個範圍内的所有文本,使用下面文法:

$ awk 'NR==M, NR==N' filename

把M跟N換成數字

$ seq 100 | awk 'NR==4, NR==6'

要列印處于'/start_pattern/,/end_pattern/' filename 

$ cat section.txt

line with pattern1

line with pattern2

line with pattern3

line end with pattern4

line with pattern5

$awk '/pa.*3/, /end/' section

回文判斷 最簡單的使用指令rev指令

rev 接受一個檔案或stdin作為輸入,并逆序列印每一行内容

試試下面的代碼

<code>#/bin/bah</code>

<code>string=</code><code>"malayalam"</code>

<code>if</code> <code>[[ </code><code>"$string"</code> <code>== </code><code>"$(echo $string | rev )"</code> <code>]]; </code><code>#重點</code>

<code>echo</code> <code>"Palindrome"</code>

<code>else</code>

<code>echo</code> <code>"not palindrome"</code>

解析文本中的點子郵件位址和url

解析email

egrep -o '[A-Za-z0-9.]+@[A-Za-z0-9.]+\.[a-zA-Z]{2,4}'

比對HTTP URL的正規表達式

egrep -o "http://[a-zA-Z0-9.]+\.[a-zA-A]{2,3}"

http://www.google.com

http://code.google.com

[a-zA-Z0-9.]+ “+”表示應該出現多次

用awk實作head、tail和tac

$ awk 'NR &lt;=10' filename

模拟tail指令列印檔案的後10行

$ awk '{ buffer[NR % 10] = $0;} END { for(i=1;i&lt;11;i++){print buffur[i%10] } }' filename

檔案切片與參數操作

替換變量内容中的部分文本

$ var="this is a line of text"

$ echo ${var/line/REPLACED}

"This is a REPLACED of text"

$name ${name%$1}$2  #${name%\.*} "%"号除去字尾名,隻取檔案名

${file_name#*.} 隻留擴充名或字尾

生成子竄

${variable_name:start_positon:length}

最後一個字元索引記為-1,使用負數索引的話,必須将負數放入括号内,例如(-1)就是最後一個字元的索引

如 

string={a..z}

echo ${string:(-2):2}

yz

本文轉自lilin9105 51CTO部落格,原文連結:http://blog.51cto.com/7071976/1251296,如需轉載請自行聯系原作者

繼續閱讀