歡迎加入QQ討論群258996829
來自星星的你 頭像
蘋果3袋
3
來自星星的你

識(shí)別Mac電腦上文件的命令行技巧

發(fā)布時(shí)間:2015-01-19 21:09  回復(fù):0  查看:3585   最后回復(fù):2015-01-19 21:09  

(原文:File it Away 作者:Mark Dalrymple 譯者:Mr_cyz
有時(shí)你會(huì)因一個(gè)文件而迷惑,這個(gè)文件可能是在你的文件夾中的一個(gè)未知類型的文件,它可能是你的父母或者客戶給你的。不幸的是,你不知道它到底是一種什么樣的文件。在Mac上文件是不帶有拓展名的,所以可能并沒有足夠的信息來告訴你“Flongnozzle-2012”到底包含了什么內(nèi)容。然而終端(Terminal)可以為你提供一些便利,你可以使用一些內(nèi)嵌的命令行工具來幫助你鑒別文件。

識(shí)別文件內(nèi)容

對(duì)于這種情況,file命令恰好是我所需要的。file指令可以檢測(cè)一個(gè)文件的內(nèi)容然后試圖去弄清楚它是什么。

% file launchHandler.m
launchHandler.m: ASCII C++ program text
當(dāng)然,這其實(shí)是Objective-C文件,不過終端已經(jīng)非常接近了,終端將其鑒別為一個(gè)內(nèi)有代碼的文件?!暗鹊龋琈arkD(注:作者),它僅僅看下文件的拓展名不就行了嗎?”file命令也支持這種情況,不過拓展名并不是必須的:

% cp launchHandler.m splunge
% file splunge
splunge: ASCII C++ program text
沒有文件拓展名,不過我們依然鑒別出了這個(gè)文件是什么。將file命令指向一個(gè)可能包含可執(zhí)行代碼的文件或目錄,它會(huì)告訴你其內(nèi)在的結(jié)構(gòu):

% file /bin/ls
/bin/ls: Mach-O 64-bit executable x86_64
你可能會(huì)說,如果你有一個(gè)體積龐大的二進(jìn)制文件(例如,原生的App)怎么辦,下面是辦法:

% file /Applications/Reason/Reason.app/Contents/MacOS/Reason
Reason.app/Contents/MacOS/Reason: Mach-O universal binary with 2 architectures
Reason.app/Contents/MacOS/Reason (for architecture i386): Mach-O executable i386
Reason.app/Contents/MacOS/Reason (for architecture x86_64): Mach-O 64-bit executable x86_64
將file指向一個(gè)圖片文件來看看圖片的一些信息:

% file Flongnozzle-2012
Flongnozzle-2012: PNG image data, 1932 x 904, 8-bit/color RGB, non-interlaced

哦等等,這里有一個(gè)終端的使用小技巧:將文件的圖標(biāo)從Finder中拖入終端窗口,這就相當(dāng)于將你拖動(dòng)的這個(gè)文件或文件夾的完整路徑粘貼進(jìn)去了。

進(jìn)一步探索

有時(shí)file也不會(huì)讓你滿意,或者你可能想要知道關(guān)于文件的更多信息。一般來說,你總是可以通過QuickLook在Finder中瀏覽一下文件,如果這樣不起作用,那么你可以使用hexdump命令來看看出文件的字節(jié)數(shù),也可以傳入?yún)?shù)-c來看看翻譯成ASCII碼之后的信息。

例如,回到我們之前的那個(gè)圖片文件:

% hexdump -C Flongnozzle-2012 | head
00000000  89 50 4e 47 0d 0a 1a 0a  00 00 00 0d 49 48 44 52  |.PNG........IHDR|
00000010  00 00 07 8c 00 00 03 88  08 02 00 00 00 a2 e0 9b  |................|
00000020  61 00 00 0c 45 69 43 43  50 49 43 43 20 50 72 6f  |a...EiCCPICC Pro|
00000030  66 69 6c 65 00 00 48 0d  ad 57 77 54 53 c9 17 be  |file..H..WwTS...|
00000040  af 24 81 90 84 12 88 80  94 d0 9b 28 bd 4a ef 82  |.$.........(.J..|
在展示出來的數(shù)據(jù)區(qū)并沒有太多有用信息,但是你可以看到它是PNG類型的,這已經(jīng)是比較有用了,有些文件還含有更多字符串類型的內(nèi)容,下面是對(duì)一個(gè)從 Reason 數(shù)碼音頻工作室獲得的補(bǔ)丁文件使用hexdump指令得到的信息:

% hexdump -C CV-Spy--md.cmb
00000000  46 4f 52 4d 00 00 03 d8  50 54 43 48 43 41 54 20  |FORM....PTCHCAT |
00000010  00 00 00 04 52 45 46 53  43 4f 49 4e 00 00 00 06  |....REFSCOIN....|
00000020  bc 01 00 00 00 01 43 41  54 20 00 00 00 fc 44 45  |......CAT ....DE|
00000030  56 4c 46 4f 52 4d 00 00  00 f0 44 45 56 49 44 45  |VLFORM....DEVIDE|
00000040  53 43 00 00 00 47 bc 02  01 00 00 07 00 00 00 10  |SC...G..........|
00000050  00 00 00 12 43 56 20 56  61 6c 75 65 73 20 28 30  |....CV Values (0|
00000060  2d 3e 32 35 36 29 00 00  00 00 00 00 00 00 00 00  |->256)..........|
00000070  00 00 16 44 44 4c 20 44  69 67 69 74 61 6c 20 44  |...DDL Digital D|
00000080  65 6c 61 79 20 4c 69 6e  65 00 00 00 04 00 50 41  |elay Line.....PA|
...

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

strings命令可以從文件中得到像字符串一樣的字節(jié)序列:

% strings CV-Spy--md.cmb
FORM
PTCHCAT
REFSCOIN
CAT
DEVLFORM
DEVIDESC
CV Values (0->256)
DDL Digital Delay Line
...

屬性值

屬性列表(Property lists)是Mac和iOS系統(tǒng)上的一種標(biāo)準(zhǔn)類型的文件,將一些可以預(yù)知類型的數(shù)據(jù)有結(jié)構(gòu)地組織起來就構(gòu)成了我們的plist文件。在該系統(tǒng)上,一般你看到的屬性列表文件都是被壓縮成二進(jìn)制格式的文件,這樣在讀取時(shí)會(huì)更快。用戶的偏好設(shè)置就被存儲(chǔ)為plist文件:

% pwd
/Users/markd/Library/Preferences
% file com.apple.iphonesimulator.plist
com.apple.iphonesimulator.plist: Apple binary property list
不幸的是,這個(gè)壓縮之后的plist文件是一種非常難讀的文件:

% hexdump -C com.apple.iphonesimulator.plist
00000000  62 70 6c 69 73 74 30 30  dc 01 02 03 04 05 06 07  |bplist00........|
00000010  08 09 0a 0b 0c 0d 0e 0f  10 11 12 13 14 15 16 17  |................|
00000020  18 5e 53 69 6d 75 6c 61  74 65 44 65 76 69 63 65  |.^SimulateDevice|
00000030  5f 10 2f 4e 53 57 69 6e  64 6f 77 20 46 72 61 6d  |_./NSWindow Fram|
00000040  65 20 69 50 68 6f 6e 65  53 69 6d 75 6c 61 74 6f  |e iPhoneSimulato|
00000050  72 57 69 6e 64 6f 77 2e  32 2e 30 2e 37 35 30 30  |rWindow.2.0.7500|
00000060  30 30 5f 10 2f 4e 53 57  69 6e 64 6f 77 20 46 72  |00_./NSWindow Fr|
00000070  61 6d 65 20 69 50 68 6f  6e 65 53 69 6d 75 6c 61  |ame iPhoneSimula|
...

幸運(yùn)的是,有一個(gè)工具plutil指令能將這樣二進(jìn)制形式的數(shù)據(jù)轉(zhuǎn)換為更接近與人類可讀語言的形式:

360桌面截圖20150119134029.jpg

(“!$”快捷鍵用來獲取上一條指令中得最后一個(gè)參數(shù))

Spotlight

在解讀一個(gè)特定文件方面,OS可能做得比你想象得更好。Spotlight的工作就是為磁盤上的文件編制索引,通過查詢?cè)獢?shù)據(jù)來讓本地搜索更方便快捷。你可以通過mdls命令來獲取這個(gè)元數(shù)據(jù),所以你能夠問問Spotlight對(duì)于這個(gè)文件都知道些什么:

% mdls launchHandler.m
kMDItemContentCreationDate     = 2014-07-02 19:22:02 +0000
kMDItemContentModificationDate = 2014-07-02 19:23:58 +0000
kMDItemContentType             = "public.objective-c-source"
kMDItemContentTypeTree         = (
    "public.objective-c-source",
    "public.source-code",
    "public.plain-text",
    "public.text",
    "public.data",
    "public.item",
    "public.content"
)
...
kMDItemKind                    = "Objective-C Source"
kMDItemLastUsedDate            = 2014-07-02 19:32:46 +0000
kMDItemLogicalSize             = 1443
kMDItemPhysicalSize            = 4096
kMDItemUseCount                = 2
kMDItemUsedDates               = (
    "2014-07-02 10:00:00 +0000"

這里mdls告訴你這個(gè)文件是Objective-C代碼的源文件,同時(shí)還有其他相同類型的標(biāo)識(shí)符來描述數(shù)據(jù),這確實(shí)是代碼的源文件,并且是文本編輯格式。當(dāng)然也有一些有趣的數(shù)據(jù),例如這個(gè)文件到底在磁盤上占據(jù)著多少空間,以及這個(gè)文件由多少字節(jié)組成。

加載服務(wù)(Launch Services)

另一個(gè)維護(hù)系統(tǒng)數(shù)據(jù)庫信息的工具是加載服務(wù),它決定著哪個(gè)應(yīng)用會(huì)打開哪個(gè)文件。雙擊一個(gè)文件來打開它?Finder會(huì)去詢問加載服務(wù)。在命令行使用open指令來打開文件?系統(tǒng)也會(huì)去詢問加載服務(wù),由它來辨別到底由誰去打開文件。

lsappinfo指令就是一個(gè)使用加載服務(wù)(當(dāng)然還有核心應(yīng)用服務(wù),Core Application Services)的工具,它能給你一些關(guān)于現(xiàn)在正在運(yùn)行的應(yīng)用的信息。這與辨別文件到底是什么無關(guān),但是有了它,你就能了解到一些很cool的信息。試一下使用lsappinfo sharedmemory命令來獲得共享內(nèi)存的信息?;蛘呤褂胠sappinfo visibleProcessList命令列出一組現(xiàn)可見的應(yīng)用程序(順序?yàn)榘创翱趶那暗胶螅?

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

/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister
lsregister主要被用于在OS系統(tǒng)上注冊(cè)一個(gè)文件,這個(gè)文件將會(huì)由特定的應(yīng)用程序來處理。不過你可以dump它的數(shù)據(jù)庫來查看相關(guān)信息,使用:

% lsregister -dump > services-db.txt

(要運(yùn)行該指令,你需要擴(kuò)展你的PATH,加入Support目錄)。

這條指令產(chǎn)生了大概61000行輸出,因此這對(duì)于一個(gè)日常教程來說就有些太笨重了,不過瀏覽一下也是挺有趣的。

還有一些有用的功能來自于一個(gè)調(diào)用:LSCopyApplicationURLsForURL。給這個(gè)調(diào)用傳入一個(gè)文件的路徑作為參數(shù),它會(huì)返回一組可以處理該文件的應(yīng)用集合。它有不同的查詢模式,像“能打開這個(gè)文件的所有的應(yīng)用程序有哪些?”,或者“能編輯這個(gè)文件的所有應(yīng)用程序有哪些?”加載服務(wù)并不像file指令一樣去內(nèi)探這個(gè)文件的結(jié)構(gòu)。取而代之的是,它利用文件的拓展名、源代碼、模糊匹配來找出合適的應(yīng)用。

這里有一個(gè)小工具,它需要在命令行傳入一個(gè)文件名。通過調(diào)用LSCopyApplicationURLsForURL,打印出匹配出來的應(yīng)用程序的數(shù)組。你可以在這里找到這個(gè)源代碼。

@import Foundation;
@import CoreServices;
 
// clang -g -fobjc-arc -fmodules launchHandler.m -o launchHandler
 
int main (int argc, const char *argv[]) {
 
    // Rudimentary argument checking.
    if (argc != 2) {
        printf ("usage: %s filename\n", argv[0]);
        return -1;
    }
 
    const char *filename = argv[1];
 
    // Get a string of the full path of the file, using realpath() as the workhorse
    char pathbuffer[MAXPATHLEN];
    char *fullpath = realpath (filename, pathbuffer);
    if (fullpath == NULL) {
        fprintf (stderr, "could not find %s\n", filename);
        return -1;
    }
 
    NSURL *url = [NSURL fileURLWithPath: @( fullpath )];
 
    // Ask launch services for the different apps that it thinks could edit this file.
    // This is usually a more useful list than what can view the file.
    LSRolesMask roles = kLSRolesEditor;
    CFArrayRef urls = LSCopyApplicationURLsForURL((__bridge CFURLRef)url, roles);
    NSArray *appUrls = CFBridgingRelease(urls);
 
    // Extract the app names and sort them for prettiness.
    NSMutableArray *appNames = [NSMutableArray arrayWithCapacity: appUrls.count];
 
    for (NSURL *url in appUrls) {
        [appNames addObject: url.lastPathComponent];
    }
    [appNames sortUsingSelector: @selector(compare:)];
 
    // Finally emit to the user.
    for (NSString *appName in appNames) {
        printf ("%s\n", appName.UTF8String);
    }
 
    return 0;
 
} // main
最有趣的部分是這里用的是realpath()庫,通過調(diào)用它來將命令行參數(shù)中的文件名轉(zhuǎn)換為完整路徑(所以你不用擔(dān)心如果用戶到底傳入的是一個(gè)相對(duì)路徑,還是一個(gè)絕對(duì)路徑,還是一個(gè)帶~的路徑),然后將它傳入LSCopyApplicationURLsForURL,這里還使用了kLSRolesEditor,因?yàn)樗梢苑祷刈詈侠淼囊唤M應(yīng)用程序。有時(shí)候選的應(yīng)用程序也能給你一些線索來判斷這個(gè)文件到底是什么。

% ./launchHandler launchHandler.m
TextEdit.app
Xcode-4.6.app
Xcode-5.0.2.app
Xcode.app
Xcode6-Beta2.app
 
% ./launchHandler someGraphic.png
Acorn.app
ColorSync Utility.app
Preview.app
 
% ./launchHandler ./Flongnozzle-2012
%

不幸的是,它并不能解決“Flongnozzle”是什么的問題,因?yàn)檫@個(gè)文件沒有拓展名或者其他有用的文件類型的信息。

其他工具

可用的命令行工具集非同尋常得多,因此我很可能落下了一個(gè)或者兩個(gè)或者更多其他的工具來幫助你辨別一個(gè)未知文件。如果你有一個(gè)非常喜歡的小技巧,請(qǐng)留下一條評(píng)論!

您還未登錄,請(qǐng)先登錄

熱門帖子

最新帖子

?