
Atualmente eu uso o seguintecomando simplificadopararemover espaço em branco à direitaeadicione uma nova linha no final do arquivoonde necessário:
find . -type f -exec sed -i -e 's/[ \t]\+\(\r\?\)$/\1/;$a\' {} \+
Como você verá rapidamente, isso tem dois problemas: vai mudararquivos bináriose adicionará uma nova linha ao final dos arquivos com␍␊ separadores de linha. Essas modificações são fáceis de desfazer ou pular ao confirmar git gui
ou algo semelhante, mas eu gostaria de minimizar* a quantidade de reversão. Para esse fim:
Existe uma maneira de pular otodoarquivo sequalquerlinha corresponde a uma regex em sed
?
* Estou ciente de que pode haver arquivos binários sem caracteres ␀ e pode haver arquivos com novas linhas ou ␀s deliberadamente misturados. Mas procuro a solução que requer o mínimo de intervenção humana. EUpoderiapossivelmente listaria todas as extensões de arquivo nas quais eu gostaria de operar, mas seria uma lista muito longa que teria que ser revisada constantemente e, devido a conflitos de nomes, ainda seria possível que arquivos binários escapassem.
ComplicadoGambiarra:
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)
Responder1
Se você confia git
no ponto de vista de sobre o que é um arquivo binário ou não, você pode usar git grep
para obter uma lista de arquivos não binários. Supondo que t.cpp
seja um arquivo de texto e ls
um binário, ambos foram verificados:
$ ls
t.cpp ls
$ git grep -I --name-only -e ''
t.cpp
A -I
opção significa:
-I
Não corresponda ao padrão em arquivos binários.
Para combinar isso com sua sed
expressão:
$ git grep -I --name-only -z -e '' | \
xargs -0 sed -i.bk -e 's/[ \t]\+\(\r\?\)$/\1/;$a\'
( -z
/ xargs -0
para ajudar com nomes de arquivos estranhos.)
Confira a git grep
página de manual para outras opções úteis - --no-index
ou --cached
pode ajudar dependendo exatamente do conjunto de arquivos em que você deseja operar.
Responder2
Existe uma maneira de pular o arquivo inteiro se alguma linha corresponder a uma regex no sed?
Sim existe.
# 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
Responder3
Aqui está um script Perl que itera sobre seus argumentos (que devem ser nomes de arquivos) e anexa uma nova linha a cada arquivo que não termina em uma nova linha. Arquivos contendo um byte nulo são ignorados. Arquivos que já terminam em nova linha não são modificados. Arquivos que contêm um CR são anexados ao CRLF, outros recebem apenas LF. Não testado.
#!/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;
}
}