首先說明一下,這裡的裸是指不事先判斷目錄是否存在,直接使用 mkdir -p 建立。
如果經常與檔案系統打交道,少不了會有建立目錄的操作。
比如,我們想在某台機器上同步某個檔案目錄,就需要確定它的父目錄存在。如果不存在,可能還需要根據需要動态建立。
系統提供了很多可以直接使用的指令,它的好處是顯而易見的,當你不想在遠端裝 agent 來操作,而選擇使用 ssh 連接配接,直接使用這些現成指令是一個簡單有效的選擇。
如果建立目錄,可以選擇使用 mkdir 指令。如果系統可能有多級目錄不存在,我們可能會考慮 -p 選項。
-p 類似于程式設計裡面的遞歸思想,但是有一點要注意注意注意,它是從檔案系統的根開始判斷的,而不是從最完整的目錄。
strace mkdir -p /tmp/foo/bar/bazz/baxx/apple/boy/cat/dog
# ...
mkdir("/tmp", ) = - EEXIST (File exists)
chdir("/tmp") =
mkdir("foo", ) =
open("foo", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) =
fchdir() =
close() =
mkdir("bar", ) =
open("bar", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) =
fchdir() =
close() =
mkdir("bazz", ) =
open("bazz", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) =
fchdir() =
close() =
mkdir("baxx", ) =
open("baxx", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) =
fchdir() =
close() =
mkdir("apple", ) =
open("apple", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) =
fchdir() =
close() =
mkdir("boy", ) =
open("boy", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) =
fchdir() =
close() =
mkdir("cat", ) =
open("cat", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) =
fchdir() =
close() =
mkdir("dog", ) =
# ...
天哪,每一級目錄,如果存在,會對應兩個系統調用(mkdir、chdir);如果不存在,會對應四個系統調用(mkdir、open、fchdir、close)。
當偶而執行一次這類操作,問題倒還不是特别明顯。但是當我們頻繁執行大量與此類似的深層目錄建立的操作時,系統的性能很快就會有所反應。
好的實踐是怎樣的呢?
首先,我們要建立的目錄很有可能已經存在。這一步判斷可以避免 mkdir -p 無條件地執行。test 可以判斷目錄或檔案是否存在,它隻是一個簡單的 stat 系統調用,very cheap。
其次,避免使用絕對路徑。如果我們确定 /tmp/foo/bar/bazz/baxx/apple 已經存在,隻需要從 apple 建立 boy/cat/dog 這三個目錄就可以了,可以節省 1 * 2 + 5 * 4 = 22 次系統調用,這次真是賺到了。
當然,如果隻是手動建立目錄,-p 并沒有太大的副作用。視情況而定。