識別Mac電腦上檔案的命令列技巧

發表於2015-04-26

有時你會因一個檔案而迷惑,這個檔案可能是在你的資料夾中的一個未知型別的檔案,它可能是你的父母或者客戶給你的。不幸的是,你不知道它到底是一種什麼樣的檔案。在Mac上檔案是不帶有擴充名的,所以可能並沒有足夠的資訊來告訴你“Flongnozzle-2012”到底包含了什麼內容。然而終端(Terminal)可以為你提供一些便利,你可以使用一些內嵌的命令列工具來幫助你鑑別檔案。

識別檔案內容

對於這種情況,file命令恰好是我所需要的。file指令可以檢測一個檔案的內容然後試圖去弄清楚它是什麼。

當然,這其實是Objective-C檔案,不過終端已經非常接近了,終端將其鑑別為一個內有程式碼的檔案。“等等,MarkD(注:作者),它僅僅看下檔案的擴充名不就行了嗎?”file命令也支援這種情況,不過擴充名並不是必須的:

沒有檔案擴充名,不過我們依然鑑別出了這個檔案是什麼。將file命令指向一個可能包含可執行程式碼的檔案或目錄,它會告訴你其內在的結構:

你可能會說,如果你有一個體積龐大的二進位制檔案(例如,原生的App)怎麼辦,下面是辦法:

將file指向一個圖片檔案來看看圖片的一些資訊:

哦等等,這裡有一個終端的使用小技巧:將檔案的圖示從Finder中拖入終端視窗,這就相當於將你拖動的這個檔案或資料夾的完整路徑貼上進去了。

進一步探索

有時file也不會讓你滿意,或者你可能想要知道關於檔案的更多資訊。一般來說,你總是可以通過QuickLook在Finder中瀏覽一下檔案,如果這樣不起作用,那麼你可以使用hexdump命令來看看出檔案的位元組數,也可以傳入引數-c來看看翻譯成ASCII碼之後的資訊。

例如,回到我們之前的那個圖片檔案:

在展示出來的資料區並沒有太多有用資訊,但是你可以看到它是PNG型別的,這已經是比較有用了,有些檔案還含有更多字串型別的內容,下面是對一個從Reason數碼音訊工作室獲得的補丁檔案使用hexdump指令得到的資訊:

如果你之前用過Reason,術語“CV Values”和“DDL Digital Delay Line”你一定不會陌生。

strings命令可以從檔案中得到像字串一樣的位元組序列:

屬性值

屬性列表(Property lists)是Mac和iOS系統上的一種標準型別的檔案,將一些可以預知型別的資料有結構地組織起來就構成了我們的plist檔案。在該系統上,一般你看到的屬性列表檔案都是被壓縮成二進位制格式的檔案,這樣在讀取時會更快。使用者的偏好設定就被儲存為plist檔案:

不幸的是,這個壓縮之後的plist檔案是一種非常難讀的檔案:

幸運的是,有一個工具plutil指令能將這樣二進位制形式的資料轉換為更接近與人類可讀語言的形式:

(“!$”快捷鍵用來獲取上一條指令中得最後一個引數)

Spotlight

在解讀一個特定檔案方面,OS可能做得比你想象得更好。Spotlight的工作就是為磁碟上的檔案編制索引,通過查詢後設資料來讓本地搜尋更方便快捷。你可以通過mdls命令來獲取這個後設資料,所以你能夠問問Spotlight對於這個檔案都知道些什麼:

這裡mdls告訴你這個檔案是Objective-C程式碼的原始檔,同時還有其他相同型別的識別符號來描述資料,這確實是程式碼的原始檔,並且是文字編輯格式。當然也有一些有趣的資料,例如這個檔案到底在磁碟上佔據著多少空間,以及這個檔案由多少位元組組成。

載入服務(Launch Services)

另一個維護系統資料庫資訊的工具是載入服務,它決定著哪個應用會開啟哪個檔案。雙擊一個檔案來開啟它?Finder會去詢問載入服務。在命令列使用open指令來開啟檔案?系統也會去詢問載入服務,由它來辨別到底由誰去開啟檔案。

lsappinfo指令就是一個使用載入服務(當然還有核心應用服務,Core Application Services)的工具,它能給你一些關於現在正在執行的應用的資訊。這與辨別檔案到底是什麼無關,但是有了它,你就能瞭解到一些很cool的資訊。試一下使用lsappinfo sharedmemory命令來獲得共享記憶體的資訊。或者使用lsappinfo visibleProcessList命令列出一組現可見的應用程式(順序為按視窗從前到後)。

要獲取載入服務的其他特性可以通過API,或者是lsregister。其中lsregister算是一個眾所周知但卻非官方的工具了。lsregister在LaunchServices框架下的Support目錄內,而LaunchServices框架又被包含在CoreServices框架中。在你的機器上,很可能是下面這樣的路徑:

lsregister主要被用於在OS系統上註冊一個檔案,這個檔案將會由特定的應用程式來處理。不過你可以dump它的資料庫來檢視相關資訊,使用:

(要執行該指令,你需要擴充套件你的PATH,加入Support目錄)。

這條指令產生了大概61000行輸出,因此這對於一個日常教程來說就有些太笨重了,不過瀏覽一下也是挺有趣的。

還有一些有用的功能來自於一個呼叫:LSCopyApplicationURLsForURL。給這個呼叫傳入一個檔案的路徑作為引數,它會返回一組可以處理該檔案的應用集合。它有不同的查詢模式,像“能開啟這個檔案的所有的應用程式有哪些?”,或者“能編輯這個檔案的所有應用程式有哪些?”載入服務並不像file指令一樣去內探這個檔案的結構。取而代之的是,它利用檔案的擴充名、原始碼、模糊匹配來找出合適的應用。

這裡有一個小工具,它需要在命令列傳入一個檔名。通過呼叫LSCopyApplicationURLsForURL,列印出匹配出來的應用程式的陣列。你可以在這裡找到這個原始碼。

最有趣的部分是這裡用的是realpath()庫,通過呼叫它來將命令列引數中的檔名轉換為完整路徑(所以你不用擔心如果使用者到底傳入的是一個相對路徑,還是一個絕對路徑,還是一個帶~的路徑),然後將它傳入LSCopyApplicationURLsForURL,這裡還使用了kLSRolesEditor,因為它可以返回最合理的一組應用程式。有時候選的應用程式也能給你一些線索來判斷這個檔案到底是什麼。

不幸的是,它並不能解決“Flongnozzle”是什麼的問題,因為這個檔案沒有擴充名或者其他有用的檔案型別的資訊。

其他工具

可用的命令列工具集非同尋常得多,因此我很可能落下了一個或者兩個或者更多其他的工具來幫助你辨別一個未知檔案。如果你有一個非常喜歡的小技巧,請留下一條評論!

相關文章