Как протестировать, использует ли файл CRLF или LF, не изменяя его?

В первую очередь, Ваш вопрос не имеет никакого отношения к удару, но с терминалом. Терминал отвечает для отображения текста программ, и сам удар не имеет никакого контроля над программами, после того как они запустились.

Терминалы предлагают управляющие последовательности для управления цветом, шрифтом, позицией курсора и т.д. Поскольку список стандартизированных терминальных последовательностей взглянул на http://www.termsys.demon.co.uk/vtansi.htm, Вы можете, например,

  • расположите курсор в начале строки
  • удалите строку впоследствии
  • запишите новую строку

создать индикатор выполнения.

Более усовершенствованные терминальные escape-последовательности являются обычно терминальным зависимым, например, работа только с Eterm или xterm. ncurses - является библиотекой программирования, чтобы создать интерактивные программы с терминалом, таким образом, Вы не должны будете использовать escape-последовательности.

Как перезаписать существующую строку с терминальными последовательностями

echo long text
sleep 1
printf "\033[1A"  # move cursor one line up
printf "\033[K"   # delete till end of line
echo foo

Как перезаписать существующую строку без терминальной последовательности

Одно простое решение не состоит в том, чтобы записать новую строку в конце, но записать возврат каретки, который в основном сбрасывает курсор к началу строки, например:

echo -n first 
sleep 1 
echo -ne "\rsecond"
echo

\r или возврат каретки поместит курсор в начале строки и позволяет Вам перезаписывать содержание строки.

Переключатель между буферами как less или vi

Поведение less происходит также из-за более усовершенствованной терминальной функции, альтернативного экрана:

В режиме VT102 существуют escape-последовательности, чтобы активировать и деактивировать альтернативный экранный буфер, который является тем же размером как область дисплея окна. При активации текущий экран сохраняется и заменяется альтернативным экраном. Сохранение строк, прокрученных от вершины окна, отключено, пока нормальный экран не восстанавливается. Термин ‐ ограничение (5) запись для xterm позволяет визуальному редактору vi (1) переключаться на альтернативный экран для редактирования и восстанавливать экран на выходе. Запись всплывающего меню делает простым переключиться между нормальными и альтернативными экранами для вырезанного и вставленного.

http://rosettacode.org/wiki/Terminal_control/Preserve_screen перечисляет некоторый пример, как сделать это самостоятельно, или через tput или через некоторые escape-последовательности.

51
02.12.2015, 07:26
11 ответов

Можно использовать dos2unix как фильтр и сравнивают его вывод с исходным файлом:

dos2unix < myfile.txt | cmp -s - myfile.txt
42
27.01.2020, 19:33
  • 1
    Очень умный и полезный, потому что это тестирует полный файл и не только, первые или некоторые выравнивают. –  halloleo 19.05.2015, 03:04
  • 2
    Возможно, Вы могли заменить test myfile.txt дважды в Вашем примере для предотвращения беспорядка с /usr/bin/test. –  Peterino 30.05.2016, 10:51
  • 3
    NB необходимо будет удалить -s флаг для наблюдения вывода. Из страниц справочника: -s, --quiet, --silent suppress all normal output –  tobalr 29.01.2018, 21:20

Если цель состоит в том, чтобы только постараться не влиять на метку времени, dos2unix имеет a -k или --keepdate опция, которая сохранит метку времени тем же. Это должно будет все еще сделать запись, чтобы сделать временный файл и переименовать его, но Ваши метки времени не будут затронуты.

Если какая-либо модификация файла недопустима, можно использовать следующее решение из этого ответа.

find . -not -type d -exec file "{}" ";" | grep CRLF
26
27.01.2020, 19:33
  • 1
    Вы подразумеваете литеральную запись CRLF как 4 символов C, R, L и F? –  bodacydo 03.12.2015, 05:19
  • 2
    Вы также подразумеваете, что grep может взять CR и LF точно так же, как это? –  bodacydo 03.12.2015, 05:19
  • 3
    @bodacydo объяснено в ответе, что он связывается с, и теперь также в редактировании Scott ответа BertS здесь unix.stackexchange.com/a/79708/59699. –  dave_thompson_085 03.12.2015, 07:14
  • 4
    @dave_thompson_085 я не вижу объяснение. Это только упоминает CRLF, но не объясняет, каково это. –  bodacydo 03.12.2015, 08:05
  • 5
    @bodacydo stackoverflow.com/questions/73833 / … говорит это find ... -exec file ... | grep CRLF для файла с окончаниями строки DOS (т.е. байты 0D 0A) "получит Вас что-то как: ./1/dos1.txt: ASCII text, with CRLF line terminators Поскольку Вы видите, что это содержит фактическую строку CRLF и поэтому подобрано grep поиск простой строки CRLF. –  dave_thompson_085 04.12.2015, 10:40

Вы могли попытаться grep для кода CRLF, восьмеричного:

grep -U $'\015' myfile.txt

или шестнадцатеричное число:

grep -U $'\x0D' myfile.txt
22
27.01.2020, 19:33
  • 1
    Конечно, предположение - то, что это - текстовый файл. –  mdpc 17.06.2013, 20:24
  • 2
    мне нравится это grep использование, потому что это позволяет мне легко перечислять все такие файлы в каталоге с grep -lU $'\x0D' * и передайте вывод xargs. –  Melebius 30.04.2015, 09:19
  • 3
    , каково значение $ перед шаблоном поиска? @don_crissti –  fersarr 31.10.2017, 12:07
  • 4

Первый метод (grep):

Считайте строки, которые содержат возврат каретки:

[[ $(grep -c $'\r' myfile.txt) -gt 0 ]] && echo dos

Считайте строки, которые заканчиваются возвратом каретки:

[[ $(grep -c $'\r$' myfile.txt) -gt 0 ]] && echo dos

Они обычно будут эквивалентны; возврат каретки во внутренней части строки (т.е. не в конце) редок.

Более эффективный:

grep -q $'\r' myfile.txt && echo dos

Это более эффективно

  1. потому что это не должно преобразовать количество в строку ASCII, и затем преобразовать ту строку назад в целое число и сравнить его для обнуления, и
  2. потому что grep -c потребности считать весь файл, считать все случаи шаблона, в то время как grep -q может выйти после наблюдения первого вхождения шаблона.

Примечания:

  • Всюду по вышеупомянутому Вы, возможно, должны добавить -U опция (т.е. использование -cU или -qU), потому что GNU grep предположения, является ли файл текстовым файлом. Если это думает, что файл является текстом, это игнорирует возвраты каретки в концах строк в попытке сделать $ в работе регулярных выражений "правильно" — даже если регулярное выражение \r$! определение -U (или --binary) отвергает эти догадки, вызывая grep рассматривать файл (файлы) как двоичный файл и передать данные механизму соответствия дословно, с неповрежденными CR-окончаниями.
  • Не делать grep … $'\r\n' myfile.txt, потому что grep обработки \n как разделитель шаблона. Так же, как grep -E 'foo|' ищет строки, содержащие foo или пустая строка, grep $'\r\n' ищет строки, содержащие \r или пустая строка и каждая строка соответствуют пустой строке.

Второй метод (file):

[[ $(file myfile.txt) =~ CRLF ]] && echo dos

потому что file отчеты что-то как:

myfile.txt: UTF-8 Unicode text, with CRLF line terminators

Более безопасный вариант:

[[ $(file -b - < myfile.txt) =~ CRLF ]] && echo dos

где

Остерегайтесь той проверки вывода от file не мог бы работать в неанглийской локали.

13
27.01.2020, 19:33
  • 1
    Можно заменить "$(echo -e '\r')" с намного более простым $'\r', хотя лично я использовал бы $'\r\n' сокращать количество ложных положительных сторон. –  rici 17.06.2013, 20:03
  • 2
    @rici grep $'\r\n' кажется, соответствует всем файлам в моей системе... –  depquid 17.06.2013, 20:09
  • 3
    @rici: хорошая выгода. Я отредактировал свой ответ согласно Вашему предложению. — depquid: Возможно, Вы находитесь в Windows? :-) подсказка rici работает здесь. –  BertS 17.06.2013, 20:11
  • 4
    @depquid (и BertS): На самом деле я думаю, что корректный вызов grep -U $'\r$', предотвратить grep попытка пересмотреть окончания строки. –  rici 17.06.2013, 20:18
  • 5
    Кроме того, можно использовать -q просто установить код возврата, если соответствие найдено, вместо -c который требует дополнительной проверки. Лично мне нравится Ваше второе решение, хотя это очень зависит от прихотей file и не мог бы работать в неанглийской локали. –  rici 17.06.2013, 20:22

функция удара для Вас:

# return 0 (true) if first line ends in CR
isDosFile() {
    [[ $(head -1 "$1") == *$'\r' ]]  
}

Затем можно сделать материал как

streamFile () {
    if isDosFile /tmp/foo.txt; then
        sed 's/\r$//' "$1"
    else
        cat "$1"
    fi
}

streamFile /tmp/foo.txt | process_lines_without_CR
4
27.01.2020, 19:33
  • 1
    Вы не должны использовать isDosFile() в Вашем примере: streamFile() { sed 's/\r$//' "$1" ; }. –   17.06.2013, 21:59
  • 2
    , я думаю, что это - самое изящное решение; это не читает целый файл, просто первая строка. –  Adam Ryczkowski 22.06.2013, 23:50

Если файл будет иметь окончания строки DOS/Windows-style CR-LF, то, если Вы смотрите на него с помощью Основанного на Unix инструмента, Вы будете видеть CR ('\r') символы в конце каждой строки.

Эта команда:

grep -l '^M$' filename

распечатает filename если файл содержит одну или несколько строк с окончаниями строки стиля Windows, и ничего не распечатает, если он не делает. За исключением того, что ^M должен быть литеральный символ возврата каретки, обычно вводимый в терминал путем ввода Ctrl+V, сопровождаемого, Входят (или Ctrl+V и затем Ctrl+M). Оболочка удара позволяет Вам записать литеральный возврат каретки как $'\r' (зарегистрированный здесь), таким образом, можно записать:

grep -l $'\r$' filename

Другие оболочки могут обеспечить подобную функцию.

Можно использовать другой инструмент вместо этого:

awk '/\r$/ { exit(1) }' filename

Это выйдет с состоянием 1 (установка $? кому: 1) если файл содержит какие-либо окончания строки стиля Windows, и с состоянием 0 если это не делает, делая это полезным в оболочке if оператор (отмечают отсутствие [ скобки ]):

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

Файл может содержать смесь стиля Unix и окончаний строки стиля Windows. Я предполагаю здесь, что Вы хотите обнаружить файлы, которые имеют любые окончания строки стиля Windows.

4
27.01.2020, 19:33
  • 1
    Можно закодировать возврат каретки на командной строке в ударе (и некоторые другие оболочки) путем ввода $'\r', как упомянуто в других ответах на этот вопрос. –  Scott 02.12.2015, 08:41

Начиная с версии 7.1 dos2unix имеет параметр -i , - info для получения информации о переносах строк. Вы можете использовать сам dos2unix, чтобы проверить, какие файлы нужно преобразовать.

Пример:

dos2unix -ic *.txt | xargs dos2unix
21
27.01.2020, 19:33

Я использовал

cat -v filename.txt | diff - filename.txt

, который, кажется, работает. Я считаю, что вывод немного легче читать, чем

dos2unix < filename.txt | diff - filename.txt

. Он также полезен, если по какой-то причине вы не можете установить dos2unix .

1
27.01.2020, 19:33

Примечание. Это не следует использовать в сценариях автоматизации, только для быстрой проверки. Для сценариев автоматизации я бы посоветовал вам посмотреть другие ответы

Используйте cat -A

$ cat file
hello
hello

Теперь, если этот файл был создан в системах *NIX, он будет отображать

$ cat -A file
hello$
hello$

Но если этот файл был Windows, он будет отображать

$ cat -A file
hello^M$
hello

^Mпредставляет CRи $представляет LF. Обратите внимание, что Windows не сохранила последнюю строку с CRLF

. Это также не меняет содержимое файла.

53
27.01.2020, 19:33

Usarfile:

$ 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
6
27.01.2020, 19:33

fileпоказывает окончания строк, но только если они не в стиле Unix -:

❯ echo "hello1\nhello2\n" > hello-unix.txt
❯ cp hello-unix.txt hello-dos.txt
❯ cp hello-unix.txt hello-mac.txt
❯ unix2dos hello-dos.txt
unix2dos: converting file hello-dos.txt to DOS format...
❯ unix2mac hello-mac.txt
unix2mac: converting file hello-mac.txt to Mac format...
❯ file hello-unix.txt
hello-unix.txt: ASCII text
❯ file hello-dos.txt
hello-dos.txt: ASCII text, with CRLF line terminators
❯ file hello-mac.txt
hello-mac.txt: ASCII text, with CR line terminators

Так:

  • Если fileсообщает «окончатели строк CRLF», файл соответствует стилю DOS -
  • .
  • Если fileсообщает о терминаторах строки CR, файл соответствует стилю Mac -
  • Если в fileне упоминаются разделители строк, файл выполнен в стиле Unix -
0
17.01.2021, 16:35

Теги

Похожие вопросы