En Windows, las extensiones de archivo suelen ser lo suficientemente bueno:
# 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
Pero, por supuesto, las extensiones de archivo no son perfectos. A nadie le gusta escribir largas listas, y muchos archivos son mal nombrados de todos modos.
No creo que Unix tenga ningún indicador binario especial frente a texto en el sistema de archivos. (Bueno, VMS sí, pero dudo que esa sea la fuente de tus hábitos de grep.) Miré la implementación de Grep -I, y aparentemente es solo una heurística rápida y sucia basada en la primera parte del archivo. Resulta que es una estrategia que tengo a bit of experience con. Así que este es mi consejo sobre cómo elegir una función heurística que sea apropiada para archivos de texto de Windows:
- Examine al menos 1 KB del archivo. Muchos formatos de archivo comienzan con un encabezado que se parece al texto, pero reventará el analizador poco después. La forma en que funciona el hardware moderno, leer 50 bytes tiene aproximadamente la misma sobrecarga de E/S que leer 4 KB.
- Si solo le preocupa el ASCII directo, salga tan pronto como vea algo fuera del rango de caracteres [31-127 más CR y LF]. Es posible que accidentalmente excluyas algún arte ASCII inteligente, pero tratar de separar esos casos de la basura binaria no es trivial.
- Si desea manejar el texto Unicode, permita que las bibliotecas de MS manejen el trabajo sucio. Es más difícil de lo que piensas Desde Powershell puede acceder fácilmente al método estático IMultiLang2 interface (COM) o Encoding.GetEncoding (.NET). Por supuesto, todavía están adivinando.Los comentarios de Raymond sobre Notepad detection algorithm (y el enlace dentro de Michael Kaplan) valen la pena revisar antes de decidir exactamente cómo desea mezclar & para que coincidan con las bibliotecas proporcionadas por la plataforma.
- Si el resultado es importante, es decir, una falla hará algo peor que saturar su consola grep, entonces no tenga miedo de codificar algunas extensiones de archivos por razones de precisión. Por ejemplo, los archivos * .PDF ocasionalmente tienen varios KB de texto en el frente a pesar de ser un formato binario, lo que lleva a los errores notorios vinculados anteriormente. Del mismo modo, si tiene una extensión de archivo que probablemente contenga datos XML o de tipo XML, puede probar un esquema de detección similar al Visual Studio's HTML editor. (SourceSafe 2005 realmente toma prestado este algoritmo para algunos casos)
- Pase lo que pase, tenga un plan de copia de seguridad razonable.
Como ejemplo, aquí está el detector ASCII rápida:
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() }
}
}
}
El patrón de uso que estoy focalización es una cláusula where-objeto insertado en la tubería entre "dir" y "ss". Hay otras formas, dependiendo de su estilo de scripting.
La mejora del algoritmo de detección a lo largo de una de las rutas sugeridas se deja al lector.
edición: Empecé a responder a su comentario en un comentario de la mía, pero tengo demasiado tiempo ...
arriba, yo miraba el problema desde el POV de listas blancas conocida buenas secuencias. En la aplicación que mantuve, almacenar incorrectamente un archivo binario como texto tenía peores consecuencias que viceversa. Lo mismo es cierto para escenarios en los que se elige qué modo de transferencia FTP usar o qué tipo de codificación MIME enviar a un servidor de correo electrónico, etc.
En otras situaciones, la lista negra es obviamente falsa y permite que todo lo demás sea el texto llamado es una técnica igualmente válida. Mientras que U + 0000 es un punto de código válido, casi nunca se encuentra en el texto del mundo real. Mientras tanto, \ 00 es bastante común en archivos binarios estructurados (es decir, cuando un campo de longitud de byte fijo necesita relleno), por lo que es una gran lista negra simple. VSS 6.0 utilizó este control solo y lo hizo bien.
Además: los archivos * .zip son un caso en el que la comprobación de \ 0 es más arriesgada. A diferencia de la mayoría de los binarios, su bloque estructurado de "encabezado" (pie de página?) Está al final, no al principio. Suponiendo la compresión de entropía ideal, la posibilidad de no \ 0 en el primer 1KB es (1-1/256)^1024 o aproximadamente 2%. Afortunadamente, simplemente escaneando el resto de la lectura NTFS del clúster de 4KB disminuirá el riesgo hasta 0.00001% sin tener que cambiar el algoritmo o escribir otro caso especial.
Para excluir el UTF-8 no válido, agregue \ C0-C1 y \ F8-FD y \ FE-FF (una vez que haya buscado más allá de la posible lista de materiales) a la lista negra. Muy incompleto ya que en realidad no está validando las secuencias, pero lo suficientemente cerca para sus propósitos. Si desea obtener algo más elegante que este, es hora de llamar a una de las bibliotecas de plataforma como IMultiLang2 :: DetectInputCodepage.
No estoy seguro de por qué \ C8 (200 decimal) está en la lista de Grep. No es una codificación demasiado larga. Por ejemplo, la secuencia \ C8 \ 80 representa Ȁ (U + 0200). Tal vez algo específico de Unix.
No es un script PS, pero el equivalente 'findstr' es' findstr/p' que utilizo en la consola powershell de esta manera: 'doskey fs = findstr/spin/a: 4A $ *' luego usar como 'fs' –
orad