Quero remover o espaço em branco à direita de todos os arquivos em uma hierarquia de diretórios recursiva. Eu uso isso:
find * -type f -exec sed 's/[ \t]*$//' -i {} \;
Isso funciona, mas também remove o "espaço em branco" à direita dos arquivos binários encontrados, o que é indesejável.
Como eu digo find
para evitar executar este comando em arquivos binários?
file
que podem inspecionar os dados.Respostas:
Você pode tentar usar o
file
comando Unix para ajudar a identificar os arquivos que não deseja, mas acho que será melhor se você especificar explicitamente quais arquivos deseja acessar e não aqueles que não deseja.Para evitar passar para os arquivos de controle de origem, você pode querer algo como
Você pode ou não precisar de algumas barras invertidas, dependendo do seu shell.
fonte
-i
opção para sed . É difícil escrever um comando de shell portátil, não é?Isso pode ser feito na linha de comando.
fonte
A resposta mais simples e mais portátil é executar o seguinte:
Explico por que abaixo, onde também mostro como fazê-lo usando apenas a linha de comando e como lidar com arquivos de texto trans-ASCII como ISO-8859-1 (Latin-1) e UTF-8, que depois não possuem -ASCII em branco neles.
O resto da história
O problema é que o find (1) não suporta o
-T
operador de teste de arquivo nem reconhece as codificações - caso necessário - o que é absolutamente necessário para detectar a codificação Unicode padrão de fato UTF-8.O que você pode fazer é executar a lista de nomes de arquivos através de uma camada que gera arquivos binários. Por exemplo
No entanto, agora você tem problemas com espaço em branco nos seus nomes de arquivos, portanto, é necessário atrasá-lo com terminação nula:
Outra coisa que você poderia fazer é usar não ,
find
masfind2perl
já que Perl-T
já entende :E se você quiser que o Perl assuma que seus arquivos estão em UTF-8, use
Ou você pode salvar o script resultante em um arquivo e editá-lo. Você realmente não deve apenas executar o
-T
teste de arquivo em qualquer arquivo antigo, mas apenas naqueles que são arquivos simples, conforme determinado pela primeira vez-f
. Caso contrário, você corre o risco de abrir promoções do dispositivo, bloquear fifos etc.No entanto, se você fizer tudo isso, poderá ignorar completamente o sed (1). Por um lado, é mais portátil, pois a versão POSIX do sed (1) não entende
-i
, enquanto todas as versões do Perl o fazem. As versões dos últimos dias do sed apropriadamente se apropriaram da-i
opção muito útil do Perl, onde ti aparece pela primeira vez.Isso também oferece a oportunidade de corrigir seu regex também. Você realmente deve usar um padrão que corresponda a um ou mais espaços em branco horizontais à direita, não apenas a zero, ou será mais lento se copiar desnecessariamente. Ou seja, isso:
deveria estar
No entanto, como fazer com que o sed (1) entenda que requer uma extensão não POSIX, geralmente
-R
para os System Ⅴ Unices como Solaris ou Linux, ou-E
para os BSD como OpenBSD ou MacOS. Eu suspeito que é impossível no AIX. É quase mais fácil escrever um shell portátil do que um script de shell portátil, você sabe.Aviso em 0xA0
Embora esses sejam os únicos caracteres de espaço em branco horizontal no ASCII, tanto o ISO-8859-1 quanto o Unicode também possuem o NO-BREAK SPACE no ponto de código U + 00A0. Esse é um dos dois principais caracteres não ASCII encontrados em muitos corpora Unicode e, ultimamente, tenho visto muitas pessoas quebrando o código regex porque se esqueceram disso.
Então, por que você não faz isso:
Se você pode ter arquivos UTF-8 para lidar com, add
-CSD
, e se você estiver executando Perl V5.10 ou superior, você pode usar\h
para o espaço em branco horizontal e\R
por uma quebra de linha genérica, que inclui\r
,\n
,\r\n
,\f
,\cK
,\x{2028}
, e\x{2029}
:Isso funcionará em todos os arquivos UTF-8, independentemente de quebras de linha, eliminando o espaço em branco horizontal à direita (propriedade de caractere Unicode
HorizSpace
), incluindo o incômodo NO-BREAK SPACE que ocorre antes de uma quebra de linha Unicode (incluindo combos de CRLF) no final de cada linha.Também é muito mais portátil que a versão sed (1), porque há apenas uma implementação perl (1), mas muitas da sed (1).
O principal problema que vejo ainda existe com o find (1), já que em alguns sistemas verdadeiramente recalcitrantes (você sabe quem você é, AIX e Solaris), ele não entende a
-print0
diretiva supercrítica . Se essa é a sua situação, você deve apenas usar oFile::Find
módulo diretamente do Perl e não usar outros utilitários Unix. Aqui está uma versão Perl pura do seu código que não depende de mais nada:Se você estiver executando apenas arquivos de texto ASCII ou ISO-8859-1, tudo bem, mas se estiver executando com arquivos ASCII ou UTF-8, adicione
-CSD
aos comutadores na chamada interna para Perl.Se você tiver codificações mistas dos três ASCII, ISO-8859-1 e UTF-8, receio que você tenha outro problema. :( Você precisará descobrir a codificação por arquivo e nunca há uma boa maneira de adivinhar isso.
Espaço em branco Unicode
Para o registro, o Unicode possui 26 caracteres de espaço em branco diferentes. Você pode usar o utilitário unichars para detectá -los. Somente os três primeiros caracteres de espaço em branco horizontal são quase sempre vistos:
fonte
O GNU grep é muito bom para identificar se um arquivo é binário ou não. Além do Solaris, tenho certeza de que existem outras plataformas que não vêm com o GNU grep instalado por padrão, mas, como o Solaris, tenho certeza de que você pode instalá-lo.
Se você estiver no Solaris, substituirá
grep
por/opt/csw/bin/ggrep
.Os
grep
sinalizadores fazem o seguinte:l
lista apenas nomes de arquivos para arquivos correspondentes,R
é recursivo,I
corresponde apenas a arquivos de texto (ignora arquivos binários) eP
é para sintaxe de expressão regular compatível com perl.A parte perl modifica o arquivo no local, excluindo todos os espaços / guias finais.
Por fim: se o UTF8 for um problema, a resposta da tchrist juntamente com a minha deve ser suficiente, desde que a sua versão
grep
tenha sido construída com o suporte ao UTF8 (normalmente, os mantenedores de pacotes tentam fornecer esse tipo de funcionalidade).fonte