que tenía que hacer esto de forma recursiva, y esto es lo que ocurrió:
find -type f | while read l; do iconv -s -f utf-16le -t utf-8 "$l" | nl -s "$l: " | cut -c7- | grep 'somestring'; done
Esto es absolutamente horrible y muy lento; Estoy seguro de que hay una manera mejor y espero que alguien pueda mejorar en él - pero yo estaba en un apuro: P
Lo que hacen las piezas:
find -type f
da una lista recursiva de nombres de archivo con las rutas relativo a la actual
while read l; do ... done
Bash loop; para cada línea de la lista de rutas de archivos, ingrese la ruta en $l
y haga lo mismo en el ciclo. (Por qué utilicé un bucle de shell en lugar de xargs, lo que hubiera sido mucho más rápido: tengo que prefijar cada línea de la salida con el nombre del archivo actual. No podía pensar en una forma de hacerlo si estaba alimentando varios archivos a la vez para iconv, y ya que voy a estar haciendo un archivo al mismo tiempo de todos modos, el lazo shell es la sintaxis más fácil/escape)
iconv -s -f utf-16le -t utf-8 "$l"
convertir el archivo nombrado en $l
:. asumirá el archivo de entrada es utf-16 little-endian y lo convierte a utf-8. El -s
hace que Iconv se calle con respecto a cualquier error de conversión (habrá mucho, porque algunos archivos en esta estructura de directorio no son utf-16). El resultado de esta conversión pasa a stdout.
nl -s "$l: " | cut -c7-
Este es un truco: nl
insertos números de línea, pero pasa a tener un parámetro "utilizar esta cadena arbitraria para separar el número de la línea", por lo que poner el nombre de archivo (seguida de dos puntos y espacio) en eso. Luego uso cut
para quitar el número de línea, dejando solo el prefijo del nombre de archivo. (Por qué no usé sed
: escapar es mucho más fácil de esta manera. Si utilicé una expresión sed, tengo que preocuparme de que haya caracteres de expresión regulares en los nombres de archivo, que en mi caso eran muchos. nl
es mucho más tonto de sed
, y que acaba de tomar el parámetro -s
por completo, literalmente, y la cáscara se encarga del escape para mí.)
Así, a finales de este gasoducto, me he convertido en un montón de archivos en líneas de UTF-8 , prefijado con el nombre de archivo, que luego grep. Si hay coincidencias, puedo decir en qué archivo están del prefijo.
Advertencias
- Esto es mucho, mucho más lento que
grep -R
, porque estoy generando una nueva copia de iconv
, nl
, cut
y grep
para cada archivo. Es horrible.
- Todo lo que no sea entrada utf-16le saldrá como basura completa, por lo que si hay un archivo ASCII normal que contiene 'somestring', este comando no lo informará; también debe hacer una normal
grep -R
como este comando (y si tiene múltiples tipos de codificación Unicode, como algunos archivos big-endian y little little-endian, necesita ajustar este comando y ejecutarlo nuevamente para cada codificación diferente).
- Los archivos cuyo nombre contenga 'somestring' aparecerán en la salida, incluso si sus contenidos no coinciden.
... no es ASCII si los caracteres tienen dos bytes de longitud. –
Me refiero al rango de caracteres ASCII (U + 0000 a U + 007F), no codificación ASCII. – taw