天天看點

Linux/Unix的精巧約定兩例及其簡析:目錄權限和文本行數目錄權限的約定文本行數的約定後記

學玩*nux時候,碰到的一些問題,弄明白了後也就過去了。今天看到旁邊的同學對目錄權限有些模糊,給解釋了一下。想想不如把這些問題都記下來。

設計其實包含的是一套約定。能運作、解決問題的約定都是可用的約定。但解決的多種約定方式或說是設計中,作一些比較可以感覺到哪個會更統一更簡單。下文提到的兩例linux/unix約定說明後,我也簡單分析一下約定,找出看似複雜或是不直覺約定中内部包含的簡潔統一。

清楚的同學,就當是個活動腦子的問題,過一遍小樂一下 

Linux/Unix的精巧約定兩例及其簡析:目錄權限和文本行數目錄權限的約定文本行數的約定後記

 如有謬誤敬請指正。

普通檔案(非目錄)有執行權限、執行操作,很容易了解,目錄執行權限是個啥?

我期望以盡量簡明統一方式來描述:

目錄的執行權限 是 下面操作的前提: 該目錄下的檔案(包含子目錄)的讀、寫、執行操作(即目錄下檔案的全部操作) 該目錄本身的寫操作

注: 要對目錄進行寫操作,要同時有該目錄的寫權限 和 該目錄的執行權限。

關于上面提到的目錄的讀、寫操作的說明在下一節給出。

上面條款1實際上包含有遞歸說明:

目錄的執行權限前提要有父目錄的執行權限;

父目錄的執行權限的前提是要有父目錄的父目錄的執行權限;

……

舉個例子來講解一下,比如要讀檔案<code>/home/foo/readme.txt</code>:

要讀<code>readme.txt</code>,前提要可以執行父目錄<code>foo</code>

要執行<code>foo</code>目錄,前提要可以執行父目錄<code>home</code>

要執行<code>home</code>目錄,前提要可以執行父目錄<code>/</code>(即root目錄)root目錄沒有父目錄了(或者說,root目錄的父目錄是自己),遞歸終止。

上面分析的結果是,要讀檔案<code>/home/foo/readme.txt</code>需要:

<code>readme.txt</code>的讀權限

<code>foo</code>目錄的執行權限

<code>home</code>目錄的執行權限

<code>/</code>目錄的執行權限

通過上面分析可以看出,目錄的執行權限是對其下子檔案進行操作的前提,是以隻要對自己的home目錄的權限改成700,就可以拒絕他人檢視自己home下的檔案的内容、在目錄下建立或是删除檔案。

# 如果隻給他home目錄的讀權限,還是可以list出home下有哪些檔案,見下一節的說明

<code>$ chmod 700 . $ ls -ld . drwx----- 9 foo foo 4.0k 2012-11-20 00:11 ./</code>

注: <code>ls</code>的<code>-d</code>表示list檔案是目錄時,不去list目錄下檔案,而是list目錄本身。

普通檔案(非目錄)的讀、寫操作很容易了解。目錄的讀、寫操作說明如下:

目錄讀操作 = 可以list出目錄下有哪些檔案 寫操作 = 可以在該目錄下建立和删除這個目錄下的檔案(包含建立和删除子目錄)

注:要對目錄進行寫操作,前提要同時有該目錄的寫權限 和 該目錄的執行權限。

是以,為了删除一個現有的檔案,必須對包含該檔案的目錄具有寫權限和執行權限;對該檔案本身不需要有讀、寫權限。

目錄這些權限的約定,讓整個目錄(包含下面所有的子檔案)的控制變得簡單,簡單調整這個目錄上的執行權限就可以了;資訊集中,友善維護。

想想windows的約定吧,是不是想到那個“應用到所有子目錄和檔案”的選項,要把所有的子目錄都設定一遍。

最早開始期望一句話來描述“目錄的執行權限”,即隻有條款1,結果發現還有條款2的内容,是“該目錄本身的寫操作”的前提。

這樣不統一的描述,讓我感覺到條款2可能是unix設計為了解決一些實際問題而補入的條款。我的yy的場景是:

限制對home目錄的操作(增删子檔案,包含的遞歸子檔案),如果沒有條款2,關掉别人對home目錄執行權限還不夠,還要通過關掉别人對home目錄寫權限來限制。這樣的常見需求兩步操作就繁瑣了!

文本的行數 = 文本中換行符的個數

可以使用下面的指令驗證:

<code>$ echo -n blablabla | wc 0 1 9</code>

看到統計行數的結果是<code>0</code>行。

注: <code>echo</code>的<code>-n</code>選項表示不輸出換行。

“文本的行數 = 文本中換行符的個數”的約定,隻要找到換行就好。

不需要特殊處理最後一行可能沒有換行。

# windows下不做這個約定,就要有這樣的特殊處理。

想想寫個程式按行輸出結果。

如果輸出最後一個結果後不要換行:

<code>int len = 10; int[] result = ...; for(int i = 0; i &lt; len; ++i) { if(i != 0) { // 如果不是第一個 printf("n"); } printf("%d", i); }</code>

如果每輸出一個結果帶一個換行:

<code>int len = 10; int[] result = ...; for(int i = 0; i &lt; len; ++i) { printf("%dn", i); }</code>

這兩種寫法,第二種沒有<code>if</code>判斷,更整齊、更簡單。

從上面2種情況,一種是統計輸入文本行數,一種輸出多行文本,這個約定都簡化實作和說明。簡單是美。

你可能發現,這個約定簡單是對于程式,對于人來做就麻煩了,要保證最後一行後面有換行符!

實際上linux/unix下的文本編輯器會遵循這個約定,編輯時會自動給最後一行沒有換行的文本加上一個換行。

這樣這個約定就不會給人帶來麻煩了,讓編輯器來維護這個約定。

可以這樣驗證:

生成不帶結尾換行的檔案。

<code>$ echo -n blablabla &gt; test.txt $ wc test.txt 0 1 9 test.txt</code>

用vi打開編輯,第一行行頭加一個字元後儲存退出,wc統計一下,已經有一行文本了。

<code>$ wc test.txt 1 1 11 test.txt</code>

注: eclipse裡有時會提醒你一個warning說檔案不是以換行符結束(no newline at end of file),現在知道為什麼了吧 

Linux/Unix的精巧約定兩例及其簡析:目錄權限和文本行數目錄權限的約定文本行數的約定後記

*nix的設計和約定博大精深,以後發現些新有意思的條目會加進來。

繼續閱讀