Мне нужно периодически запускать команду, которая гарантирует, что некоторые текстовые файлы хранятся в режиме Linux. К сожалению, dos2unix
всегда изменяет файл, который может испортить временные метки файла и папки и вызвать ненужные записи.
Сценарий, который я пишу, написан на Bash, поэтому я бы предпочел ответы, основанные на Bash.
bash
text-processing
newlines
Адам Рычковски
источник
источник
test
наmyfile.txt
два раза в вашем примере , чтобы избежать путаницы с/usr/bin/test
.-s
флаг, чтобы увидеть вывод. С man-страниц:-s, --quiet, --silent suppress all normal output
Если цель состоит в том, чтобы просто не влиять на временную метку,
dos2unix
есть опция-k
или,--keepdate
которая будет сохранять временную метку на том же уровне. Он все равно должен будет сделать запись, чтобы создать временный файл и переименовать его, но ваши временные метки не будут затронуты.Если любое изменение файла неприемлемо, вы можете использовать следующее решение из этого ответа .
источник
find ... -exec file ... | grep CRLF
для файла с окончанием строки DOS (т. е. байты 0D 0A) "вы получите что-то вроде:./1/dos1.txt: ASCII text, with CRLF line terminators
Как вы можете видеть, он содержит фактическую строку CRLF и, следовательно, соответствуетgrep
поиску простая строка CRLFВы можете попробовать
grep
для кода CRLF, восьмеричное:или гекс:
источник
grep
использование, потому что оно позволяет мне легко перечислить все такие файлы в каталогеgrep -lU $'\x0D' *
и передать результатxargs
.Начиная с версией
7.1
dos2unix имеет-i
,--info
возможность получить информацию о разрывах строк. Вы можете использовать сам dos2unix для проверки того, какие файлы нуждаются в преобразовании.Пример:
источник
Первый метод (
grep
):Подсчитайте строки, содержащие возврат каретки:
Подсчитайте строки, которые заканчиваются возвратом каретки:
Как правило, они будут эквивалентны; возврат каретки во внутренней части строки (т.е. не в конце) встречается редко.
Более эффективным:
Это более эффективно
grep -c
необходимо прочитать весь файл, чтобы подсчитать все вхождения шаблона, в то время какgrep -q
может выйти, увидев первое вхождение шаблона.Примечания:
-U
параметр (например, использовать-cU
или-qU
), потому что GNUgrep
определяет, является ли файл текстовым файлом. Если он думает, что файл является текстом, он игнорирует возврат каретки на концах строк, пытаясь заставить$
регулярные выражения работать «правильно» - даже если регулярное выражение есть\r$
! Указание-U
(или--binary
) отменяет это предположение, заставляяgrep
обрабатывать файл (ы) как двоичные и дословно передавать данные в механизм сопоставления с неизменными CR-окончаниями.grep … $'\r\n' myfile.txt
, потому чтоgrep
трактует\n
как шаблон разделителя. Так же, какgrep -E 'foo|'
ищет строки, содержащиеfoo
или нулевую строку,grep $'\r\n'
ищет строки, содержащие\r
или нулевую строку, и каждая строка соответствует пустой строке.Второй метод (
file
):потому что
file
сообщает что-то вроде:Более безопасный вариант:
где
file -b
выводит только тип файла, а не имя файла. Без этого файл , имя которого включает символыCRLF
, вызовет ложное срабатывание.file - < filename
работает, даже еслиfilename
начинается с-
. Смотрите сценарий Bash: проверьте, является ли файл текстовым файлом .Помните, что проверка выходных данных
file
может не работать в неанглийской локали.источник
"$(echo -e '\r')"
на гораздо более простой$'\r'
, хотя лично я бы использовал,$'\r\n'
чтобы уменьшить количество ложных срабатываний.grep $'\r\n'
кажется, соответствует всем файлам в моей системе ...grep -U $'\r$'
, чтобы неgrep
пытаться угадать окончания строк.-q
просто установить код возврата, если найдено совпадение, вместо-c
которого требуется дополнительная проверка. Лично мне нравится ваше второе решение, хотя оно сильно зависит от прихотейfile
и может не работать в неанглийском языке.использование
cat -A
Теперь, если этот файл был создан в системах * NIX, он будет отображать
Но если этот файл был сделан в Windows, он будет отображать
^M
представляетCR
и$
представляетLF
. Обратите внимание, что Windows не сохранила последнюю строку сCRLF
Это также не меняет содержимое файла.
источник
-A
чтобы кот. Один совет, однако, будет использовать,cat -A file | less
если файл слишком большой. Я уверен, что нередко приходится проверять окончание файла для особенно длинного файла. (Нажмите,q
чтобы оставить меньше)функция bash для вас:
Тогда вы можете делать такие вещи, как
источник
isDosFile()
в вашем примере:streamFile() { sed 's/\r$//' "$1" ; }
.Если файл имеет окончания строки CR-LF в стиле DOS / Windows, то если вы посмотрите на него с помощью инструмента на основе Unix, вы увидите символы CR ('\ r') в конце каждой строки.
Эта команда:
будет печатать,
filename
если файл содержит одну или несколько строк с окончаниями строк в стиле Windows, и ничего не печатать, если это не так. За исключением того, что это^M
должен быть буквальный символ возврата каретки, обычно вводимый в терминале, набирая Ctrl+ с Vпоследующим Enter (или Ctrl+ Vи затем Ctrl+ M). Оболочка bash позволяет вам записать буквальный возврат каретки как$'\r'
( документировано здесь ), так что вы можете написать:Другие оболочки могут предоставлять аналогичную функцию.
Вместо этого вы можете использовать другой инструмент:
Это завершится со статусом
1
(установка$?
на1
), если файл содержит какие-либо окончания строк в стиле Windows, и со статусом,0
если это не так, что делает его полезным в операторе оболочкиif
(обратите внимание на отсутствие[
скобок]
):Файл может содержать сочетание концов строк в стиле Unix и Windows. Я предполагаю , что здесь , что вы хотите , чтобы обнаружить файлы , которые имеют какие - либо окончания строк для Windows стиля.
источник
$'\r'
, как упоминалось в других ответах на этот вопрос.Используйте
file
:источник
Я использую
который, кажется, работает. Я нахожу вывод немного легче, чем читать
Это также полезно, если вы не можете установить
dos2unix
по какой-либо причине.источник