天天看點

《進階Bash腳本程式設計指南》學習筆記(9)——基礎:檔案測試操作符

如果下面的條件成立将會傳回真:

-e
檔案存在
-a
檔案存在,這個選項的效果與-e相同. 但是它已經被"棄用"了, 并且不鼓勵使用.
-f
表示這個檔案是一個一般檔案(并不是目錄或者裝置檔案)
-s
檔案大小不為零
-d
表示這是一個目錄
-b
表示這是一個塊裝置(軟碟, 光驅, 等等.)
-c
表示這是一個字元裝置(鍵盤, modem, 聲霸卡, 等等.)
-p
這個檔案是一個管道
-h
這是一個符号連結
-L
這是一個符号連結
-S
表示這是一個socket
-t
檔案(描述符)被關聯到一個終端裝置上
這個測試選項一般被用來檢測腳本中的stdin([ -t 0 ]) 或者stdout([ -t 1 ])是否來自于一個終端.
-r
檔案是否具有可讀權限(指的是正在運作這個測試指令的使用者是否具有讀權限)
-w
檔案是否具有可寫權限(指的是正在運作這個測試指令的使用者是否具有寫權限)
-x
檔案是否具有可執行權限(指的是正在運作這個測試指令的使用者是否具有可執行權限)
-g
set-group-id(sgid)标記被設定到檔案或目錄上
如果目錄具有sgid标記的話, 那麼在這個目錄下所建立的檔案将屬于擁有這個目錄的使用者組, 而不必是建立這個檔案的使用者組. 這個特性對于在一個工作組中共享目錄非常有用.
-u
set-user-id (suid)标記被設定到檔案上
如果一個root使用者所擁有的二進制可執行檔案設定了set-user-id标記位的話, 那麼普通使用者也會以root權限來運作這個檔案. [1] 這對于需要通路系統硬體的執行程式(比如pppd和cdrecord)非常有用. 如果沒有suid标志的話, 這些二進制執行程式是不能夠被非root使用者調用的.
-rwsr-xr-t    1 root       178236 Oct  2  2000 /usr/sbin/pppd
           
對于設定了suid标志的檔案, 在它的權限列中将會以s表示.
-k
設定粘貼位
對于"粘貼位"的一般了解, save-text-mode标志是一個檔案權限的特殊類型. 如果檔案設定了這個标志, 那麼這個檔案将會被儲存到緩存中, 這樣可以提高通路速度. [2] 粘貼位如果設定在目錄中, 那麼它将限制寫權限. 對于設定了粘貼位的檔案或目錄, 在它們的權限标記列中将會顯示t.
drwxrwxrwt    7 root         1024 May 19 21:26 tmp/
           
如果使用者并不擁有這個設定了粘貼位的目錄, 但是他在這個目錄下具有寫權限, 那麼這個使用者隻能在這個目錄下删除自己所擁有的檔案. 這将有效的防止使用者在一個公共目錄中不慎覆寫或者删除别人的檔案. 比如說/tmp目錄. (當然, 目錄的所有者或者root使用者可以随意删除或重命名其中的檔案.)
-O
判斷你是否是檔案的擁有者
-G
檔案的group-id是否與你的相同
-N
從檔案上一次被讀取到現在為止, 檔案是否被修改過
f1 -nt f2
檔案f1比檔案f2新
f1 -ot f2
檔案f1比檔案f2舊
f1 -ef f2
檔案f1和檔案f2是相同檔案的硬連結
!
"非" -- 反轉上邊所有測試的結果(如果沒給出條件, 那麼傳回真).

ex:測試那些斷掉的連結檔案(比較難,以後了解)

#!/bin/bash
# broken-link.sh
# 由Lee bigelow所編寫 <[email protected]>
# 已經争得作者的授權引用在本書中.

#一個純粹的shell腳本用來找出那些斷掉的符号連結檔案并且輸出它們所指向的檔案.
#以便于它們可以把輸出提供給xargs來進行處理 :)
#比如. broken-link.sh /somedir /someotherdir|xargs rm
#
#下邊的方法, 不管怎麼說, 都是一種更好的辦法:
#
#find "somedir" -type l -print0|\
#xargs -r0 file|\
#grep "broken symbolic"|
#sed -e 's/^\|: *broken symbolic.*$/"/g'
#
#但這不是一個純粹的bash腳本, 最起碼現在不是.
#注意: 謹防在/proc檔案系統和任何死循環連結中使用!
##############################################################


#如果沒有參數被傳遞到腳本中, 那麼就使用
#目前目錄. 否則就是用傳遞進來的參數作為目錄
#來搜尋.
####################
[ $# -eq 0 ] && directorys=`pwd` || directorys=$@

#編寫函數linkchk用來檢查傳遞進來的目錄或檔案是否是連結, 
#并判斷這些檔案或目錄是否存在. 然後列印它們所指向的檔案.
#如果傳遞進來的元素包含子目錄, 
#那麼把子目錄也放到linkcheck函數中處理, 這樣就達到了遞歸的目的.
##########
linkchk () {
    for element in $1/*; do
    [ -h "$element" -a ! -e "$element" ] && echo \"$element\"
    [ -d "$element" ] && linkchk $element
    # 當然, '-h'用來測試符号連結, '-d'用來測試目錄.
    done
}

#把每個傳遞到腳本的參數都送到linkchk函數中進行處理, 
#檢查是否有可用目錄. 如果沒有, 那麼就列印錯誤消息和
#使用資訊.
################
for directory in $directorys; do
    if [ -d $directory ]
	then linkchk $directory
	else 
	    echo "$directory is not a directory"
	    echo "Usage: $0 dir1 dir2 ..."
    fi
done

exit 0