Você pode usar dos2unix como filtro e comparar sua saída com o arquivo original:
dos2unix < myfile.txt | cmp -s - myfile.txt
Eu preciso executar periodicamente um comando que garanta que alguns arquivos texto sejam mantidos no modo Linux. Infelizmente dos2unix sempre modifica o arquivo, o que bagunçaria os registros de data e hora da pasta e causaria gravações desnecessárias.
O script que eu escrevo está no Bash, então prefiro respostas baseadas no Bash.
Você pode usar dos2unix como filtro e comparar sua saída com o arquivo original:
dos2unix < myfile.txt | cmp -s - myfile.txt
Se o objetivo é apenas evitar a afetação do registro de data e hora, dos2unix tem a opção -k ou --keepdate , que manterá o registro de data e hora igual. Ele ainda terá que fazer uma gravação para criar o arquivo temporário e renomeá-lo, mas seus timestamps não serão afetados.
Se qualquer modificação do arquivo for inaceitável, você pode usar a seguinte solução de esta resposta .
find . -not -type d -exec file "{}" ";" | grep CRLF
Você pode tentar grep do código CRLF, octal:
grep -U $'5' myfile.txt
ou hex:
grep -U $'\x0D' myfile.txt
Como a versão 7.1 dos2unix tem uma opção -i , --info para obter informações sobre quebras de linha. Você pode usar o dos2unix para testar quais arquivos precisam de conversão.
Exemplo:
dos2unix -ic *.txt | xargs dos2unix
grep ): Conte as linhas que contêm um retorno de carro:
[[ $(grep -c $'\r' myfile.txt) -gt 0 ]] && echo dos
Conte as linhas que terminam com <> um retorno de carro:
[[ $(grep -c $'\r$' myfile.txt) -gt 0 ]] && echo dos
Estes serão tipicamente equivalentes; um retorno de carro no interior de uma linha (ou seja, não no final) é raro.
Mais eficiente:
grep -q $'\r' myfile.txt && echo dos
Isso é mais eficiente
grep -c precisa ler o arquivo inteiro
contar todas as ocorrências do padrão,
enquanto grep -q pode sair ao ver a primeira ocorrência do padrão. Notas:
-U
(por exemplo, use -cU ou -qU ),
porque GNU grep adivinha se o arquivo é um arquivo de texto.
Se ele acha que o arquivo é texto, ele ignora os retornos de carro nas extremidades das linhas,
em uma tentativa de fazer com que $ em expressões regulares funcione "corretamente" -
mesmo se a expressão regular for \r$ !
A especificação de -U (ou --binary ) substitui essa suposição,
fazendo com que grep trate o (s) arquivo (s) como binário
e passar os dados para o mecanismo de correspondência textualmente, com as terminações CR intactas. grep … $'\r\n' myfile.txt ,
porque grep trata \n como um delimitador de padrão.
Assim como grep -E 'foo|' procura linhas contendo foo ou uma string nula,
grep $'\r\n' procura linhas contendo \r ou uma string nula,
e cada linha corresponde a uma string nula. file ): [[ $(file myfile.txt) =~ CRLF ]] && echo dos
porque file informa algo como:
myfile.txt: UTF-8 Unicode text, with CRLF line terminators
Variante mais segura:
[[ $(file -b - < myfile.txt) =~ CRLF ]] && echo dos
onde
file -b gera apenas o tipo de arquivo e não o nome do arquivo.
Sem isso, um arquivo cujo nome incluía os caracteres CRLF
provocaria um falso positivo. file - < filename funciona
mesmo que filename comece com - .
Consulte Bash script: verifique se um arquivo é um arquivo de texto arquivo de texto .
Cuidado com a verificação da saída de file
pode não funcionar em uma localidade diferente do inglês.
Use cat -A
$ cat file
hello
hello
Agora, se esse arquivo foi criado em sistemas * NIX, ele será exibido
$ cat -A file
hello$
hello$
Mas se esse arquivo foi criado no Windows, ele será exibido
$ cat -A file
hello^M$
hello
^M representa CR e $ representa LF . Observe que o Windows não salvou a última linha com CRLF
Isso também não altera o conteúdo do arquivo.
uma função bash para você:
# return 0 (true) if first line ends in CR
isDosFile() {
[[ $(head -1 "$1") == *$'\r' ]]
}
Então você pode fazer coisas como
streamFile () {
if isDosFile /tmp/foo.txt; then
sed 's/\r$//' "$1"
else
cat "$1"
fi
}
streamFile /tmp/foo.txt | process_lines_without_CR
Se um arquivo tiver terminações de linha CR-LF no estilo DOS / Windows, se você olhar para ele usando uma ferramenta baseada em Unix, verá caracteres CR ('\ r') no final de cada linha.
Este comando:
grep -l '^M$' filename
imprimirá filename se o arquivo contiver uma ou mais linhas com terminações de linha no estilo do Windows e não imprimirá nada se isso não acontecer. Exceto que ^M tem que ser um caractere de retorno de carro literal, normalmente inserido no terminal digitando Ctrl + V seguido por Enter
(ou Ctrl + V e depois Ctrl + M ). O shell bash permite que você escreva um retorno de carro literal como $'\r' ( documentado aqui ), então você pode escrever:
grep -l $'\r$' filename
Outras camadas podem fornecer uma característica semelhante.
Você pode usar outra ferramenta:
awk '/\r$/ { exit(1) }' filename
Isso sairá com um status de 1 (configurando $? para 1 ) se o arquivo contiver qualquer final de linha no estilo do Windows e com um status 0 , se não tiver, tornando útil em uma instrução shell if (observe a falta de [ colchetes ] ):
if awk '/\r$/ { exit(1) }' filename ; then
echo filename has Unix-style line endings
else
echo filename has at least one Windows-style line ending
fi
Um arquivo pode conter uma mistura de terminações de linha estilo Unix e estilo Windows. Estou assumindo aqui que você deseja detectar arquivos que tenham quaisquer terminações de linha no estilo do Windows.
Use file :
$ file README.md
README.md: ASCII text, with CRLF line terminators
$ dos2unix README.md
dos2unix: converting file README.md to Unix format...
$ file README.md
README.md: ASCII text
Eu tenho usado
cat -v filename.txt | diff - filename.txt
que parece funcionar. Eu acho a saída um pouco mais fácil de ler do que
dos2unix < filename.txt | diff - filename.txt
Também é útil se você não puder instalar dos2unix por algum motivo.
Tags bash text-processing newlines