在Windows上,文件擴展名通常是不夠好:
# all C# and related files (projects, source control metadata, etc)
dir -r -fil *.cs* | ss foo
# exclude the binary types most likely to pollute your development workspace
dir -r -exclude *exe, *dll, *pdb | ss foo
# stick the first three lines in your $profile (refining them over time)
$bins = new-list string
$bins.AddRange([string[]]@("exe", "dll", "pdb", "png", "mdf", "docx"))
function IsBin([System.IO.FileInfo]$item) { !$bins.Contains($item.extension.ToLower()) }
dir -r | ? { !IsBin($_) } | ss foo
當然不過,文件擴展名是不完美的。沒有人喜歡打字長名單,並且大量文件無論如何都是錯誤的。
我不認爲Unix在文件系統中有任何特殊的二進制文本指示器。 (好吧,VMS的確如此,但我懷疑這是你的grep習慣的根源。)我看了一下Grep -I的實現,顯然它只是基於文件第一部分的快速n-dirty啓發式。原來這是一個我有a bit of experience的策略。所以這裏是我的建議,選擇適合Windows文本文件的啓發式功能:
- 檢查至少1KB的文件。很多文件格式都以一個看起來像文本的標題開頭,但不久之後就會破解你的解析器。現代硬件的工作方式,讀取50字節與讀取4KB大致相同的I/O開銷。
- 如果你只關心直線ASCII,只要看到字符範圍外的內容[31-127加上CR和LF]就退出。您可能會意外地排除一些聰明的ASCII藝術,但試圖將這些情況與二進制垃圾分開是非平凡的。
- 如果你想處理Unicode文本,讓MS庫處理骯髒的工作。這比你想象的更難。從Powershell您可以輕鬆訪問靜態方法(.NET)IMultiLang2 interface(COM)或Encoding.GetEncoding。當然,他們仍然只是猜測。雷蒙德對Notepad detection algorithm(以及邁克爾卡普蘭內部的鏈接)的評論值得重新審視,然後再決定你想如何混合&匹配平臺提供的庫。
- 如果結果很重要 - 即一個缺陷會造成比糟糕的grep控制檯更糟糕的事情 - 那麼爲了準確起見,不要害怕對某些文件擴展名進行硬編碼。例如,* .PDF文件儘管是二進制格式,但偶爾也會有幾KB的文本,導致上面鏈接的臭名昭着的錯誤。同樣,如果您的文件擴展名可能包含XML或類似XML的數據,則可以嘗試類似於Visual Studio's HTML editor的檢測方案。 (SourceSafe 2005實際上在某些情況下借用了此算法)
- 無論發生什麼事,都要制定合理的備份計劃。
作爲一個例子,這裏的快速檢測ASCII:
function IsAscii([System.IO.FileInfo]$item)
{
begin
{
$validList = new-list byte
$validList.AddRange([byte[]] (10,13))
$validList.AddRange([byte[]] (31..127))
}
process
{
try
{
$reader = $item.Open([System.IO.FileMode]::Open)
$bytes = new-object byte[] 1024
$numRead = $reader.Read($bytes, 0, $bytes.Count)
for($i=0; $i -lt $numRead; ++$i)
{
if (!$validList.Contains($bytes[$i]))
{ return $false }
}
$true
}
finally
{
if ($reader)
{ $reader.Dispose() }
}
}
}
我針對的使用模式是與「目錄」,「SS」的管道插入其中,賓語從句。還有其他方法,這取決於您的腳本風格。
沿着一條建議路徑改進檢測算法留給讀者。
編輯:我開始回答在我自己的評論您的評論,但它得到了太久......
以上,我看着這個問題從白名單已知良好序列的POV。在我所維護的應用程序中,錯誤地將二進制文件存儲爲文本的後果遠比反之亦然。對於選擇使用哪種FTP傳輸模式或要發送到電子郵件服務器的MIME編碼類型等情況也是如此。在其他情況下,將明顯虛假列入黑名單並允許其他所有內容都是黑名單所謂的文本是一個同樣有效的技術。雖然U + 0000是一個有效的代碼點,但它在現實世界中幾乎找不到。同時,\ 00在結構化二進制文件中很常見(即每當固定字節長度的字段需要填充時),因此它成爲一個非常簡單的黑名單。 VSS 6.0單獨使用此檢查並確定。
另外:* .zip文件是檢查\ 0風險較高的一種情況。與大多數二進制文件不同,它們的結構化「標題」(頁腳?)塊在結尾,而不是開頭。假設理想的熵壓縮,前1KB中無\ 0的機會是(1-1/256)^ 1024或大約2%。幸運的是,只需掃描其餘的4KB羣集NTFS讀取操作,就可以將風險降低到0.00001%,而無需更改算法或編寫其他特例。
要排除無效的UTF-8,請將\ C0-C1和\ F8-FD和\ FE-FF(一旦您搜索到可能的物料清單後)添加到黑名單。非常不完整,因爲你實際上沒有驗證序列,但足夠接近你的目的。如果你想獲得更多的發現,現在是時候調用其中一個平臺庫,比如IMultiLang2 :: DetectInputCodepage。
不知道爲什麼\ C8(200十進制)在Grep的名單上。這不是一個超長的編碼。例如,序列\ C8 \ 80代表Ȁ(U + 0200)。也許是特定於Unix的東西。
不是PS腳本,而是`findstr`等價的是`findstr/p`,我在PowerShell控制檯中使用這樣的:`doskey fs = findstr/spin/a:4A $ *`然後像`fs` –
orad
2014-05-21 20:18:42