
Actualmente uso lo siguientecomando simplificadoaeliminar espacios en blanco al finalyagregar una nueva línea al final del archivodonde sea necesario:
find . -type f -exec sed -i -e 's/[ \t]\+\(\r\?\)$/\1/;$a\' {} \+
Como verá rápidamente, esto tiene dos problemas: cambiaráarchivos binariosy agregará una nueva línea al final de los archivos con␍␊ separadores de línea. Estas modificaciones son fáciles de deshacer u omitir cuando se confirman git gui
o similares, pero me gustaría minimizar* la cantidad de reversiones. Con ese fin:
¿Hay alguna manera de saltarse elenteropresentar sicualquier¿La línea coincide con una expresión regular en sed
?
* Soy consciente de que puede haber archivos binarios sin caracteres ␀ y podría haber archivos con nuevas líneas o ␀ mezcladas deliberadamente. Pero estoy buscando la solución que requiera la mínima intervención humana. IpodríaPosiblemente enumere todas las extensiones de archivos con las que me gustaría operar, pero sería una lista muy larga que tendría que revisarse constantemente y, debido a conflictos de nombres, aún sería posible que los archivos binarios se escapen.
Complicadosolución alterna:
while IFS= read -r -d '' -u 9
do
if [[ "$(file -bs --mime-type -- "$REPLY")" = text/* ]]
then
sed -i -e 's/[ \t]\+\(\r\?\)$/\1/;$a\' -- "$REPLY"
else
echo "Skipping $REPLY" >&2
fi
done 9< <(find . -type f -print0)
Respuesta1
Si confía git
en el punto de vista de qué es un archivo binario o no, puede utilizarlo git grep
para obtener una lista de archivos no binarios. Suponiendo que t.cpp
es un archivo de texto y ls
un binario, ambos registrados:
$ ls
t.cpp ls
$ git grep -I --name-only -e ''
t.cpp
La -I
opción significa:
-I
No coincida con el patrón en archivos binarios.
Para combinar eso con tu sed
expresión:
$ git grep -I --name-only -z -e '' | \
xargs -0 sed -i.bk -e 's/[ \t]\+\(\r\?\)$/\1/;$a\'
( -z
/ xargs -0
para ayudar con nombres de archivos extraños).
Consulte la git grep
página de manual para ver otras opciones útiles, --no-index
o --cached
podrían resultar útiles dependiendo exactamente del conjunto de archivos con los que desee operar.
Respuesta2
¿Hay alguna manera de omitir todo el archivo si alguna línea coincide con una expresión regular en sed?
Sí hay.
# test case for skipping file if a sed regex match succeeds
echo 'Hello, world!' > hello_world.txt
cat hello_world.txt
ls -li hello_world.txt
sed -i -e '/.*Hello.*/{q;}; s/world/WORLD/g' hello_world.txt # skips file
sed -i -e '/.*HeLLo.*/{q;}; s/world/WORLD/g' hello_world.txt
Respuesta3
Aquí hay un script Perl que itera sobre sus argumentos (que deben ser nombres de archivos) y agrega una nueva línea a cada archivo que no termina en una nueva línea. Se omiten los archivos que contienen un byte nulo. Los archivos que ya terminan en una nueva línea no se modifican. A los archivos que contienen un CR se les agrega CRLF, a otros solo se les agrega LF. No probado.
#!/usr/bin/env perl
foreach my $f (@ARGV) {
open F, "<", $f or die;
my $last = undef;
my $cr = 0;
while (<>) {if (/\0/) {undef $last; break} $last = $_; ++$cr if /\r$/}
close F;
if (defined $last && $last !~ /\n\Z/) {
open F, ">>", $f or die;
print($cr ? "\r\n" : "\n");
close F or die;
}
}