Quiero eliminar los espacios en blanco finales de todos los archivos en una jerarquía de directorios recursiva. Yo uso esto:
find * -type f -exec sed 's/[ \t]*$//' -i {} \;
Esto funciona, pero también eliminará el "espacio en blanco" final de los archivos binarios que se encuentran, lo que no es deseable.
¿Cómo le digo find
que evite ejecutar este comando en archivos binarios?
file
que pueden inspeccionar los datos.Respuestas:
Podría intentar usar el
file
comando Unix para ayudar a identificar los archivos que no desea, pero creo que puede ser mejor si especifica explícitamente qué archivos desea golpear en lugar de aquellos que no desea.para evitar atravesar archivos de control de origen, es posible que desee algo como
Es posible que necesite o no algunas de las barras diagonales inversas dependiendo de su caparazón.
fuente
-i
opción de sed . Es difícil escribir un comando de shell portátil, ¿no?Se puede hacer en la línea de comando.
fuente
La respuesta más simple y portátil es ejecutar esto:
Explico por qué a continuación, donde también muestro cómo hacerlo usando solo la línea de comando, así como también cómo tratar con archivos de texto trans-ASCII como ISO-8859-1 (Latin-1) y UTF-8, que a menudo tienen - Espacio en blanco ASCII en ellos.
El resto de la historia
El problema es que find (1) no es compatible con el
-T
operador de prueba de archivo, ni reconoce las codificaciones si lo hiciera, lo cual es absolutamente necesario para detectar la codificación Unicode estándar de facto UTF-8.Lo que podría hacer es ejecutar la lista de nombres de archivo a través de una capa que arroja archivos binarios. Por ejemplo
Sin embargo, ahora tiene problemas con el espacio en blanco en sus nombres de archivo, por lo que debe retrasar esto con una terminación nula:
Otra cosa que podría hacer es usar no
find
perofind2perl
, ya que Perl-T
ya lo comprende :Y si desea que Perl asuma que sus archivos están en UTF-8, use
O puede guardar el script resultante en un archivo y editarlo. Realmente no debería ejecutar la
-T
prueba de archivo en cualquier archivo antiguo, sino solo en aquellos que son archivos simples según lo determinado por primera vez-f
. De lo contrario, corre el riesgo de abrir dispositivos especiales, bloqueo en fifos, etc.Sin embargo, si va a hacer todo eso, también podría omitir sed (1) por completo. Por un lado, es más portátil, ya que la versión POSIX de sed (1) no comprende
-i
, mientras que todas las versiones de Perl sí. Las versiones recientes de sed se apropiaron con amor de la-i
opción muy útil de Perl, donde aparece por primera vez.Esto también te da la oportunidad de arreglar tu expresión regular también. Realmente debería usar un patrón que coincida con uno o más espacios en blanco horizontales finales, no solo con cero, o se ejecutará más lentamente debido a la copia innecesaria. Eso es esto:
debiera ser
Sin embargo, cómo lograr que sed (1) entienda que requiere una extensión que no sea POSIX, generalmente
-R
para sistemas System como Solaris o Linux, o-E
para BSD como OpenBSD o MacOS. Sospecho que es imposible bajo AIX. Sabes, es más fácil escribir un shell portátil que un script de shell portátil.Advertencia sobre 0xA0
Aunque esos son los únicos caracteres de espacio en blanco horizontales en ASCII, tanto ISO-8859-1 como en consecuencia también Unicode tienen el ESPACIO SIN INTERRUPCIONES en el punto de código U + 00A0. Este es uno de los dos principales caracteres no ASCII que se encuentran en muchos corpus Unicode, y últimamente he visto romper el código regex de muchas personas porque lo olvidaron.
Entonces, ¿por qué no haces esto?
Si es posible que tenga archivos UTF-8 para hacer frente, complemento
-CSD
, y si está ejecutando Perl v5.10 o superior, se puede utilizar\h
para el espacio en blanco horizontal y\R
de un salto de línea genérico, que incluye\r
,\n
,\r\n
,\f
,\cK
,\x{2028}
, y\x{2029}
:Eso funcionará en todos los archivos UTF-8 sin importar sus saltos de línea, eliminando los espacios en blanco horizontales (propiedad de caracteres Unicode
HorizSpace
), incluido el molesto ESPACIO NO-BREAK que ocurre antes de un salto de línea Unicode (incluye combos CRLF) al final de cada línea.También es mucho más portátil que la versión sed (1), porque solo hay una implementación perl (1), pero muchas de sed (1).
El principal problema que veo que queda allí es con find (1), ya que en algunos sistemas verdaderamente recalcitrantes (ya sabes quién eres, AIX y Solaris), no entenderá la
-print0
directiva supercrítica . Si esa es su situación, entonces debería usar elFile::Find
módulo de Perl directamente y no usar otras utilidades de Unix. Aquí hay una versión pura de Perl de su código que no se basa en nada más:Si solo está ejecutando archivos de texto ASCII o ISO-8859-1, está bien, pero si está ejecutando archivos ASCII o UTF-8, agréguelos
-CSD
a los interruptores en la llamada interior a Perl.Si tiene codificaciones mixtas de los tres ASCII, ISO-8859-1 y UTF-8, entonces me temo que tiene otro problema. :( Deberá averiguar la codificación por archivo, y nunca hay una buena manera de adivinar eso.
Espacio en blanco Unicode
Para el registro, Unicode tiene 26 caracteres de espacio en blanco diferentes. Puede usar la utilidad unichars para detectarlos . Solo se ven los primeros tres caracteres de espacio en blanco horizontales:
fuente
GNU grep es bastante bueno para identificar si un archivo es binario o no. Aparte de Solaris, estoy seguro de que hay otras plataformas que no vienen con GNU grep instalado de forma predeterminada, pero como Solaris, estoy seguro de que puedes instalarlo.
Si está en Solaris, lo reemplazaría
grep
con/opt/csw/bin/ggrep
.Los
grep
indicadores hacen lo siguiente:l
solo enumera nombres de archivos para archivos coincidentes,R
es recursivo,I
solo coincide con archivos de texto (ignora archivos binarios) yP
es para sintaxis de expresión regular compatible con perl.La parte perl modifica el archivo en el lugar, eliminando todos los espacios / pestañas finales.
Por último: si UTF8 es un problema, la respuesta de tchrist junto con la mía debería ser suficiente, siempre que la compilación de
grep
usted haya sido construida con soporte UTF8 (aunque los mantenedores de paquetes intentan proporcionar ese tipo de funcionalidad).fuente