Linux_Shell腳本學習第三章-以文件之名(上)

一、生產任意大小的文件

包含隨機數據的文件可用於測試。你可以使用這種文件測試應用程序效率,確定應用程序沒有輸入方面的缺陷和大小方面的限制,創建環迴文件系統(環迴文件自身包含文件系統,這種文件可以像物理設備一樣使用mount命令進行掛載)等。Linux提供了一些可用於構建此類文件的實用工具。

1.1 dd

dd命令會克隆給定的輸入內容,然後將一模一樣的一份副本寫入到輸出。stdin、設備文件、普通文件等都可作爲輸入,stdout、設備文件、普通文件等也可作爲輸出。

$ dd if=/dev/zero of=junk.data bs=1M count=1
1+0 records in
1+0 records out
1048576 bytes (1.0 MB) copied, 0.00767266 s, 137 MB/s

該命令會創建一個內容全部爲零的1MB大小的文件junk.data。
來看一下命令參數:
 if表示輸入文件(input file);
 of表示輸出文件(output file);
 bs指定了以字節爲單位的塊大小(block size);
 count表示需要被複制的塊數。
塊大小(bs)可以使用各種計量單位,如下圖。
在這裏插入圖片描述
如果不指定輸入參數(if),dd會從stdin中讀取輸入。如果不指定輸出參數(of),則dd會使用stdout作爲輸出。
使用dd命令也能夠用來測量內存操作的速度,這可以通過向/dev/null傳輸大量數據並觀察命令輸出來實現(例如,在前一個例子中顯示出的1048576 bytes (1.0 MB) copied,0.00767266 s, 137 MB/s)。

二、文本文件的交集與差集

2.1 comm

comm命令可用於比較兩個已排序的文件。它可以顯示出第一個文件和第二個文件所獨有的行以及這兩個文件所共有的行。該命令有一些選項可以禁止顯示指定的列,以便於執行交集和求差操作。
 交集(intersection):打印出兩個文件所共有的行。
 求差(difference):打印出指定文件中所包含的互不相同的那些行。
 差集(set difference):打印出包含在文件A中,但不包含在其他指定文件(例如B和C)中的那些行。

需要注意的是comm必須使用兩個排過序的文件作爲輸入。下面是我們用到的輸入文件:

$ cat A.txt
apple
orange
gold
silver
steel
iron

$ cat B.txt
orange
gold
cookies
carrot
$ sort A.txt -o A.txt ; sort B.txt -o B.txt

2.1.1 不帶任何選項

$ comm A.txt B.txt
apple
		carrot
		cookies
				gold
iron
				orange
silver
steel

輸出的第一列包含只在A.txt中出現的行,第二列包含只在B.txt中出現的行,第三列包含A.txt和B.txt中共有的行。各列之間以製表符(\t)作爲分隔符。

2.1.2 打印兩個文件的交集

爲了打印兩個文件的交集,我們需要刪除前兩列,只打印出第三列。-1選項可以刪除第一列,-2選項可以刪除第二列,最後留下的就是第三列:

$ comm A.txt B.txt -1 -2
gold
orange

2.1.3 打印出兩個文件中互不相同的那些行

$ comm A.txt B.txt -3
apple
		carrot
		cookies
iron
silver
steel

可以使用tr(在第2章中講到過)刪除製表符來合併兩列:

$ comm A.txt B.txt -3 | tr -d '\t'
apple
carrot
cookies
iron
silver
steel

2.1.4 打印出兩個文件差集

A.txt的差集

$ comm A.txt B.txt -2 -3

B.txt的差集

$ comm A.txt B.txt -1 -3

三、文件權限、所有權與粘滯位

ls命令的-l選項可以顯示出包括文件類型、權限、所有者以及組在內的多方面信息:

-rw-r--r-- 1 slynux users 2497 2010-02-28 11:22 bot.py
drwxr-xr-x 2 slynux users 4096 2010-05-27 14:31 a.py
-rw-r--r-- 1 slynux users 539 2010-02-10 09:11 cl.pl

第1列表明瞭文件類型。
 -:普通文件。
 d:目錄。
 c:字符設備。
 b:塊設備。
 l:符號鏈接。
 s:套接字。
 p:管道。

接下來的9個字符可以劃分成三組,每組3個字符(— --- —)。第一組的3個字符對應用戶權限(所有者),第二組對應用戶組權限,第三組對應其他用戶權限。這9個字符(即9個權限)中的每一個字符指明是否其設置了某種權限。如果已設置,對應位置上會出現一個字符,否則出現一個-,表明沒有設置對應的權限。

目錄有一個叫作粘滯位(sticky bit)的特殊權限。如果目錄設置了粘滯位,只有創建該目錄的用戶才能刪除目錄中的文件,就算用戶組和其他用戶也有寫權限,仍無能無力。粘滯位出現在其他用戶權限組中的執行權限(x)位置。它使用t或T來表示。如果沒有設置執行權限,但設置了粘滯位,就使用T;如果同時設置了執行權限和粘滯位,就使用t。例如:

------rwt , ------rwT

設置目錄粘滯位的一個典型例子就是/tmp,也就是說任何人都可以在該目錄中創建文件,但只有文件的所有者才能刪除其所創建的文件。

3.1 chmod

3.1.1 設置權限

假設需要設置權限:rwx rw- r-。
可以像下面這樣使用chmod:

$ chmod u=rwx g=rw o=r filename

命令中用到的選項如下。
 u:指定用戶權限。
 g:指定用戶組權限。
 o:指定其他用戶權限。

3.1.2 爲某用戶添加權限

可以用+爲用戶、用戶組和其他用戶添加權限,用-取消權限。
爲已經具有權限rwx rw- r-的文件添加可執行權限:

$ chmod o+x filename

該命令爲其他用戶添加了x權限。

給所有權限類別(即用戶、用戶組和其他用戶)添加可執行權限:

$ chmod a+x filename

3.1.3 刪除權限

如果需要刪除權限,則使用-,例如:

$ chmod a-x filename

3.2 權限表示

權限也可以使用3位八進制數來表示,每一位按順序分別對應用戶、用戶組和其他用戶。
讀、寫和執行權限都有與之對應的唯一的八進制數:

 r =  4
 w = 2
 x = 1

我們可以相加權限對應的八進制值得到所需的權限組合。例如:

 rw- = 4 + 2 = 6
 r-x = 4 + 1 = 5

權限rwx rw- r–的數字表示形式如下:

 rwx = 4 + 2 + 1 = 7
 rw- = 4 + 2 = 6
 r-- = 4

因此,rwx rw- r-- 等於764,那麼使用八進制值設置權限的命令爲:

$ chmod 764 filename

3.2 更改文件所有權

可以使用chown命令更改文件或目錄的所有權:

$ chown user:group filename

例如:

$ chown slynux:users test.sh

在這裏,slynux是用戶名,users是組名。

3.3 設置粘滯位

粘滯位可以應用於目錄。設置粘滯位後,只有目錄的所有者才能夠刪除目錄中的文件,即使其他人有該目錄的寫權限也無法執行刪除操作。
可以使用chmod的+t選項設置:

$ chmod a+t directory_name

3.4 以遞歸方式設置文件權限

有時候需要以遞歸的方式修改當前目錄下的所有文件和子目錄的權限。chmod的-R選項能夠實現這種需求:

$ chmod 777 . -R

選項-R指定以遞歸的方式修改權限。
我們用.指定當前工作目錄,這等同於:

$ chmod 777 "$(pwd)" -R

3.5 以遞歸的方式設置所有權

用chown命令的-R能夠以遞歸的方式設置所有權:

$ chown user:group . -R

3.6 以不同的身份運行可執行文件(setuid)

**一些可執行文件需要以另一種身份來運行。**例如,http服務器會在系統啓動期間由root負責運行,但是該進程應該屬於用戶httpd。setuid權限允許其他用戶以文件所有者的身份來執行文件。
首先將文件的所有權更改爲需要執行該文件的用戶,然後以該用戶的身份登錄。運行下面的命令:

$ chmod +s executable_file
# chown root:root executable_file
# chmod +s executable_file
$ ./executable_file

現在,無論是誰發起調用,該文件都是以root用戶的身份來執行。
關於setuid的詳解

三、將文件設置爲不可修改

在所有的Linux文件系統中都可以設置讀、寫、可執行以及setuid權限。除此之外,擴展文件系統(例如ext2、ext3、ext4)還支持其他屬性。其中一種擴展屬性就是可以設置不可修改的文件。一旦設置,包括root在內的任何用戶都無
法刪除該文件,除非撤銷其不可修改的屬性
。可以利用命令df -T或是通過查看 /etc/mtab文件來確定文件系統的類型。/etc/mtab文件的第一列指定了分區設備路徑(例如/dev/sda5),第三列指定了文件系統類型(例如ext3)。

不可修改屬性是避免文件被篡改的安全手段之一。/etc/resolv.conf文件就是這樣的一個例子。該文件包含了一組DNS服務器列表。DNS服務器負責將域名(例如packtpub.com)轉換成IP地址。它通常被設置成你所屬ISP的DNS服務器地址。但如果你更喜歡使用第三方的DNS服務器,可以修改/etc/resolv.conf,將其指向所選的服務器。可當下次你再連接到ISP時,/etc/resolv.conf又會恢復到之前的設置。爲了避免這種情況,需要將/etc/resolv.conf 設置成不可修改。

3.1 chattr

chattr命令可用於更改擴展屬性。它能夠將文件設置爲不可修改,也可以修改其他屬性來調節文件系統同步或壓縮率。

3.1.1 使用chatter將文件設置爲不可修改

# chattr +i file
# rm file
# rm: cannot remove 'file': Operation not permitted

3.1.2 撤銷不可修改屬性

chattr -i file

四、批量生成空白文件

4.1 touch

4.1.1 調用touch命令並使用一個不存在的文件名作爲參數,創建空白文件

$ touch filename

4.1.2 批量生成不同名字的空白文件

for name in {1..100}.txt
do
	touch $name
done

在上面的代碼中,{1…100}會擴展成一個字符串1, 2, 3, 4, 5, 6, 7…100。除了
{1…100}.txt,我們還可以使用其他簡寫樣式,比如 test{1…200}.c、test{a…z}.txt等。

4.1.3 想更改時間戳

 touch -a 只更改文件訪問時間。
 touch -m 只更改文件修改時間。
除了將時間戳更改爲當前時間,我們還能夠指定特定的時間和日期:

$ touch -d "Fri Jun 25 20:50:14 IST 1999" filename

-d使用的日期串不需要是嚴格的格式。它可以接受多種短格式日期。我們可以忽略具體時間,使用Jan 20, 2010這種格式。

五、查找符號鏈接及其指向目標

5.1 創建符號鏈接

$ ln -s target symbolic_link_name

例如:

$ ln -l -s /var/www/ ~/web

這個命令在當前用戶的主目錄中創建了一個名爲Web的符號鏈接。該鏈接指向/var/www

5.2 來驗證鏈接是否已建立

$ ls -l web
lrwxrwxrwx 1 slynux slynux 8 2010-06-25 21:34 web -> /var/www

web -> /var/www表明web指向 /var/www。

5.3 打印出當前目錄下的符號鏈接

$ ls -l | grep "^l"

^表示字符串的起始位置。其後的l指定了字符串必須以l開頭,
這標識了一個符號鏈接①。

5.4 打印出當前目錄及其子目錄下的符號鏈接

$ find . -type l -print

5.5 使用readlink打印出符號鏈接所指向的目標路徑

$ readlink web
/var/www

五、枚舉文件類型統計信息

5.1 枚舉文件類型統計信息

5.1.1 打印文件類型信息

$ file filename
$ file /etc/passwd
/etc/passwd: ASCII text

5.1.2 打印不包括文件名在內的文件類型信息

$ file -b filename
ASCII text

5.2 遍歷大量文件並收集相關細節的腳本

  1 #!/bin/bash
  2 
  3 if [ $# -ne 1 ];
  4 then
  5         echo "Usage is $0 basepath"
  6         exit
  7 fi
  8 
  9 path=$1
 10 
 11 declare -A statarrary;
 12 
 13 while read line;
 14 do
 15         ftype=`file -b "$line" | cut -d, -f1`
 16         let statarrary["$ftype"]++;
 17 
 18 done < <(find $path -type f -print)
 19 
 20 echo =========File type and coubts=========
 21 
 22 for type in "${!statarrary[@]}";
 23 do
 24         echo $type : ${statarrary["$ftype"]}
 25 done

find命令使用選項-type f返回$path所定義的目錄下的文件列表。read命令一次讀取一個文件名。當read接收到EOF(文件末尾)時,它返回假,while命令退出。

在while循環中,file命令用於確定文件類型。-b選項只顯示出文件類型(不包含文件名)。file命令能夠提供很多細節信息,比如圖像編碼以及分辨率(如果是圖像文件的話)。各種細節信息由逗號分隔,例如:

$ file a.out -b
ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not
stripped

我們只需要從上面這些信息中提取ELF 32-bit LSB executable。因此使用-d,指明以逗號作爲分隔符,使用-f1選擇第一個字段。

<(find $path -type f -print)等同於文件名。只不過它用子進程輸出來代替文件名。
注意,第一個<用於輸入重定向,第二個<用於將子進程的輸出轉換成文件名。在兩個<之間有一個空格,避免shell將其解釋爲<<操作符。

${!statarray[@]}用於返回數組的索引列表。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章