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