Preciso executar periodicamente um comando que garanta que alguns arquivos de texto sejam mantidos no modo Linux. Infelizmente, dos2unix
sempre modifica o arquivo, o que atrapalha os carimbos de data e hora das pastas e arquivos e causa gravações desnecessárias.
O script que escrevo está no Bash, então prefiro respostas baseadas no Bash.
bash
text-processing
newlines
Adam Ryczkowski
fonte
fonte
test
pormyfile.txt
duas vezes no seu exemplo de confusão evitar com/usr/bin/test
.-s
sinalizador para ver a saída. De páginas do manual:-s, --quiet, --silent suppress all normal output
Se o objetivo é apenas evitar afetar o registro de data e hora,
dos2unix
tem uma opção-k
ou--keepdate
que manterá o registro de data e hora igual. Ainda será necessário fazer uma gravação para criar o arquivo temporário e renomeá-lo, mas seus carimbos de data e hora não serão afetados.Se qualquer modificação do arquivo for inaceitável, você pode usar a seguinte solução nesta resposta .
fonte
find ... -exec file ... | grep CRLF
para um arquivo com terminações de linha DOS (ou seja bytes 0D 0A) "vai te algo como:./1/dos1.txt: ASCII text, with CRLF line terminators
Como você pode ver este contém o CRLF seqüência real e, portanto, é compensada pelagrep
procura a cadeia de caracteres simples CRLF.Você pode tentar o
grep
código CRLF, octal:ou hex:
fonte
grep
uso porque me permite listar facilmente todos esses arquivos no diretóriogrep -lU $'\x0D' *
e passar a saída paraxargs
.Como a versão
7.1
dos2unix possui uma opção-i
,--info
para obter informações sobre quebras de linha. Você pode usar o próprio dos2unix para testar quais arquivos precisam de conversão.Exemplo:
fonte
Primeiro método (
grep
):Conte as linhas que contêm um retorno de carro:
Conte as linhas que terminam com um retorno de carro:
Estes serão tipicamente equivalentes; um retorno de carro no interior de uma linha (ou seja, não no final) é raro.
Mais eficiente:
Isso é mais eficiente
grep -c
precisa ler o arquivo inteiro, contar todas as ocorrências do padrão, enquantogrep -q
pode sair ao ver a primeira ocorrência do padrão.Notas:
-U
opções acima, você pode precisar adicionar a opção (por exemplo, use-cU
or-qU
), porque o GNUgrep
adivinha se o arquivo é um arquivo de texto. Se considerar que o arquivo é texto, ele ignora os retornos de carro no final das linhas, na tentativa de fazer$
com que as expressões regulares funcionem "corretamente" - mesmo que a expressão regular seja\r$
! A especificação-U
(ou--binary
) anula essas suposições, fazendogrep
com que os arquivos sejam tratados como binários e passem os dados para o mecanismo de correspondência literalmente, com as terminações de CR intactas.grep … $'\r\n' myfile.txt
, porquegrep
trata\n
como um delimitador de padrão. Assim comogrep -E 'foo|'
procura linhas contendofoo
ou uma cadeia nula,grep $'\r\n'
procura linhas contendo\r
ou uma cadeia nula, e cada linha corresponde a uma cadeia nula.Segundo método (
file
):porque
file
relata algo como:Variante mais segura:
Onde
file -b
gera apenas o tipo de arquivo e não o nome do arquivo. Sem isso, um arquivo cujo nome incluísse os caracteresCRLF
acionaria um falso positivo.file - < filename
funciona mesmo quefilename
comece com-
. Consulte Script Bash: verifique se um arquivo é um arquivo de texto .Lembre-se de que a verificação da saída
file
pode não funcionar em um código de idioma diferente do inglês.fonte
"$(echo -e '\r')"
pelo muito mais simples$'\r'
, embora pessoalmente eu usaria$'\r\n'
para reduzir o número de falsos positivos.grep $'\r\n'
parece corresponder a todos os arquivos no meu sistema ...grep -U $'\r$'
, para evitargrep
tentar adivinhar o final da linha.-q
definir apenas o código de retorno se uma correspondência for encontrada, em vez de-c
exigir uma verificação adicional. Pessoalmente, gosto da sua segunda solução, embora seja altamente dependente dos caprichosfile
e possa não funcionar em um local diferente do inglês.Usar
cat -A
Agora, se esse arquivo foi criado em sistemas * NIX, ele exibirá
Mas se esse arquivo foi criado no Windows, ele exibirá
^M
representaCR
e$
representaLF
. Observe que o Windows não salvou a última linha comCRLF
Isso também não altera o conteúdo do arquivo.
fonte
-A
para gato. Uma dica seria usarcat -A file | less
se o arquivo for muito grande. Tenho certeza de que não é incomum ter que verificar as terminações de um arquivo particularmente longo. (Pressioneq
para deixar menos)uma função bash para você:
Então você pode fazer coisas como
fonte
isDosFile()
no seu exemplo:streamFile() { sed 's/\r$//' "$1" ; }
.Se um arquivo tiver terminações de linha CR-LF no estilo DOS / Windows, se você o usar usando uma ferramenta baseada em Unix, verá caracteres CR ('\ r') no final de cada linha.
Este comando:
será impresso
filename
se o arquivo contiver uma ou mais linhas com finais de linha no estilo Windows e não imprimirá nada se não contiver. Exceto que^M
ele deve ser um caractere literal de retorno de carro, geralmente inserido no terminal digitando Ctrl+ Vseguido de Enter (ou Ctrl+ Ve depois Ctrl+ M). O shell bash permite escrever um retorno de carro literal como$'\r'
( documentado aqui ), para que você possa escrever:Outras conchas podem fornecer um recurso semelhante.
Você pode usar outra ferramenta:
Isso sairá com um status de
1
(configurando$?
como1
) se o arquivo contiver alguma final de linha no estilo do Windows e com um status de0
se não existir, tornando-o útil em umaif
declaração de shell (observe a falta de[
colchetes]
):Um arquivo pode conter uma mistura de terminações de linha no estilo Unix e no estilo Windows. Estou assumindo aqui que você deseja detectar arquivos que têm quaisquer fins de linha de estilo do Windows.
fonte
$'\r'
, conforme mencionado em outras respostas a esta pergunta.Use
file
:fonte
Eu tenho usado
o que parece funcionar. Acho a saída um pouco mais fácil de ler do que
Também é útil se você não puder instalar
dos2unix
por algum motivo.fonte