W Windows rozszerzenia plików są zwykle wystarczająco dobre:
# 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
Ale oczywiście, rozszerzenia plików nie są doskonałe. Nikt nie lubi pisać długich list, a wiele plików i tak jest źle nazwanych.
Nie sądzę, że Unix ma jakieś specjalne wskaźniki binarne vs tekstowe w systemie plików. (Cóż, VMS to zrobił, ale wątpię, że to jest źródło twoich nawyków grep.) Spojrzałem na implementację Grepa-I, i najwyraźniej jest to po prostu szybka i brudna heurystyka oparta na pierwszej części pliku. Okazuje się, że jest to strategia, którą mam a bit of experience z. Oto moja rada dotycząca wyboru funkcji heurystycznej odpowiedniej dla plików tekstowych Windows:
- Sprawdź co najmniej 1 KB pliku. Wiele formatów plików zaczyna się od nagłówka, który wygląda jak tekst, ale wkrótce zostanie zniszczony przez twój parser. Sposób, w jaki działa nowoczesny sprzęt, odczyt 50 bajtów ma mniej więcej takie same narzuty we/wy, co odczyt 4KB.
- Jeśli zależy ci jedynie na prostym ASCII, wyjdź, gdy zobaczysz coś poza zakresem znaków [31-127 plus CR i LF]. Możesz przypadkowo wykluczyć jakąś sprytną sztukę ASCII, ale próba oddzielenia tych przypadków od binarnych śmieci jest nietrywialna.
- Jeśli chcesz obsługiwać tekst w Unicode, niech biblioteki MS obsłużą brudną pracę. To trudniejsze niż myślisz. Od Powershell można łatwo uzyskać dostęp do metody statycznej IMultiLang2 interface (COM) lub Encoding.GetEncoding (.NET). Oczywiście nadal się tylko domyślają.Uwagi Raymonda na temat Notepad detection algorithm (oraz link do Michaela Kaplana) warto przeczytać przed podjęciem decyzji, w jaki sposób chcesz mieszać & pasujące do bibliotek dostarczanych przez platformę.
- Jeśli wynik jest ważny - np. Wada zrobi coś gorszego niż po prostu zagracenie konsoli grep - to nie obawiaj się sztywnego kodowania niektórych rozszerzeń plików ze względu na dokładność. Na przykład pliki * .PDF czasami mają kilka KB tekstu z przodu, mimo że są formatem binarnym, co prowadzi do notorycznych błędów połączonych powyżej. Podobnie, jeśli masz rozszerzenie pliku, które prawdopodobnie zawiera dane XML lub podobne do XML, możesz wypróbować schemat wykrywania podobny do Visual Studio's HTML editor. (SourceSafe 2005 w rzeczywistości pożycza ten algorytm w niektórych przypadkach)
- Cokolwiek się stanie, należy mieć rozsądny plan tworzenia kopii zapasowych.
Jako przykład, oto szybki detektor 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() }
}
}
}
Wzór Wykorzystanie jestem kierowania jest klauzula gdzie-przedmiot włożony w rurociągu pomiędzy „dir” i „SS”. Istnieją inne sposoby, w zależności od stylu skryptu.
Ulepszenie algorytmu wykrywania wzdłuż jednej z sugerowanych ścieżek jest pozostawione czytnikowi.
Edit: Zacząłem odpowiedzi na Twój komentarz w komentarzu na własną rękę, ale było zbyt długo ...
Above, spojrzałem na problem z POV-białych list znany dobre sekwencje. W aplikacji, którą utrzymywałem, niepoprawne przechowywanie pliku binarnego jako tekstu miało znacznie gorsze konsekwencje niż na odwrót. To samo dotyczy scenariuszy, w których wybierasz tryb transferu FTP do użycia lub jakiego rodzaju kodowanie MIME do wysłania na serwer e-mail itp.
W innych sytuacjach na czarnej liście jest oczywiście nieprawdziwe i pozwalające na wszystko inne tekst nazywany jest równie ważną techniką. O ile U + 0000 jest prawidłowym punktem kodowym, prawie nigdy nie można go znaleźć w tekstach rzeczywistych. Tymczasem \ 00 jest dość powszechne w strukturalnych plikach binarnych (a mianowicie, gdy pole o stałej długości bajtów wymaga dopełnienia), więc tworzy świetną prostą czarną listę. VSS 6.0 użył tego czeku sam i zrobił to dobrze.
Poza: * Pliki .zip są przypadkiem, w którym sprawdzenie \ 0 jest bardziej ryzykowne. W przeciwieństwie do większości plików binarnych ich uporządkowany blok nagłówka (stopki?) Jest na końcu, a nie na początku. Zakładając idealną kompresję entropową, szansa na \ 0 w pierwszym 1KB wynosi (1-1/256)^1024 lub około 2%. Na szczęście po prostu skanowanie pozostałej części odczytu NTFS klastra 4KB spowoduje obniżenie ryzyka do 0,00001% bez konieczności zmiany algorytmu lub napisania innego specjalnego przypadku.
Aby wykluczyć nieprawidłowy kodek UTF-8, dodaj \ C0-C1 i \ F8-FD i \ FE-FF (gdy przeszukiwali Państwo możliwą LM) do czarnej listy. Bardzo niekompletne, ponieważ w rzeczywistości nie sprawdzasz poprawności sekwencji, ale wystarczająco blisko do swoich celów. Jeśli chcesz zdobyć jakikolwiek sympatyk, pora zadzwonić do jednej z bibliotek platformy, takich jak IMultiLang2 :: DetectInputCodepage.
Nie wiem, dlaczego \ C8 (200 dziesiętnych) znajduje się na liście Grepa. To nie jest zbyt długie kodowanie. Na przykład sekwencja \ C8 \ 80 reprezentuje Ȁ (U + 0200). Może coś specyficznego dla Uniksa.
Nie jest to skrypt PS, ale odpowiednik 'findstr' to' findstr/p', którego używam w konsoli PowerShell w ten sposób: 'doskey fs = findstr/spin/a: 4A $ *' następnie użyj jak 'fs' –
orad