Сценарий Bash переименовывает изображения на Mac [dубликат]

Как я могу программно (т. е. не использовать vi) преобразовать новые строки DOS / Windows в Unix?

Команды dos2unix и unix2dos недоступны в некоторых системах. Как я могу имитировать их с помощью таких команд, как sed / awk / tr?

247
задан 25 March 2018 в 18:43

19 ответов

Для Mac osx, если у вас установлен доморощенный [http://brew.sh/][1]

brew install dos2unix

for csv in *.csv; do dos2unix -c mac ${csv}; done;

Убедитесь, что вы сделали копии файлов, так как эта команда изменит файлы на месте. Параметр -c mac делает коммутатор совместимым с osx.

1
ответ дан 15 August 2018 в 15:52
  • 1
    dos2unix оказался весьма полезным! – HelloGoodbye 21 August 2014 в 20:12
  • 2
    Этот ответ действительно не является вопросом первоначального плаката. – hlin117 7 February 2015 в 21:43
  • 3
    Пользователям OS X не следует использовать -c mac, который предназначен для преобразования pre-OS X CR - только новых строк. Вы хотите использовать этот режим только для файлов в Mac OS 9 или из них. – askewchan 14 April 2016 в 16:20

Для преобразования файла на место do

dos2unix <filename>

Для вывода преобразованного текста в другой файл выполните

dos2unix -n <input-file> <output-file>

Он уже установлен на Ubuntu и доступен на домашнем [ ! d2]

brew install dos2unix

Я знаю, что вопрос явно запрашивает альтернативы этой утилите, но это первый результат поиска google для «convert dos to unix line endings».

0
ответ дан 15 August 2018 в 15:52

С помощью AWK вы можете делать:

awk '{ sub("\r$", ""); print }' dos.txt > unix.txt

С помощью Perl вы можете делать:

perl -pe 's/\r$//' < dos.txt > unix.txt
16
ответ дан 15 August 2018 в 15:52

Если у вас нет доступа к dos2unix, но вы можете прочитать эту страницу, вы можете скопировать / вставить dos2unix.py отсюда.

#!/usr/bin/env python
"""\
convert dos linefeeds (crlf) to unix (lf)
usage: dos2unix.py <input> <output>
"""
import sys

if len(sys.argv[1:]) != 2:
  sys.exit(__doc__)

content = ''
outsize = 0
with open(sys.argv[1], 'rb') as infile:
  content = infile.read()
with open(sys.argv[2], 'wb') as output:
  for line in content.splitlines():
    outsize += len(line) + 1
    output.write(line + '\n')

print("Done. Saved %s bytes." % (len(content)-outsize))

Перекрестно отправлено от суперпользователя.

10
ответ дан 15 August 2018 в 15:52
  • 1
    Использование вводит в заблуждение. Реальный dos2unix по умолчанию преобразует все входные файлы. Ваше использование подразумевает параметр -n. И настоящий dos2unix - это фильтр, который читает из stdin, записывает в stdout, если файлы не указаны. – jfs 6 July 2015 в 14:32
  • 2
    @ J.F.Sebastian, какие инструменты dos2unix реальны? Это в стандарте POSIX? – anatoly techtonik 6 July 2015 в 18:39
  • 3
    Что dos2unix вы имели в виду? Я имел в виду: sudo apt-get install dos2unix – jfs 6 July 2015 в 18:42
  • 4
    @ J.F.Sebastian Python-скрипт заканчивается на .py и не нужно следить за странными стандартами старой школьной оснастки, если он не соответствует никакому согласованному стандарту. Я нахожу его более полезным таким образом, потому что его можно использовать с инструментами построения, такими как [scons]. – anatoly techtonik 16 March 2017 в 12:11
tr -d "\r" < file

рассмотрите примеры, используя sed:

# IN UNIX ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format.
sed 's/.$//'               # assumes that all lines end with CR/LF
sed 's/^M$//'              # in bash/tcsh, press Ctrl-V then Ctrl-M
sed 's/\x0D$//'            # works on ssed, gsed 3.02.80 or higher

# IN UNIX ENVIRONMENT: convert Unix newlines (LF) to DOS format.
sed "s/$/`echo -e \\\r`/"            # command line under ksh
sed 's/$'"/`echo \\\r`/"             # command line under bash
sed "s/$/`echo \\\r`/"               # command line under zsh
sed 's/$/\r/'                        # gsed 3.02.80 or higher

Используйте здесь для преобразования в месте, например. [F5].

47
ответ дан 15 August 2018 в 15:52
  • 1
    Я использовал вариант, так как у моего файла только \r: tr "\r" "\n" < infile > outfile – Matt Todd 19 November 2010 в 04:29
  • 2
    @MattTodd вы могли бы разместить это в качестве ответа? -d показан более часто и не поможет в «только» \r ». ситуация. – n611x007 14 October 2013 в 20:20
  • 3
    Обратите внимание, что предлагаемое отображение \r - \n имеет эффект двойного перемещения файлов; каждая строка CRLF, заканчивающаяся в DOS, становится \n\n в Unix. – Jonathan Leffler 30 April 2014 в 18:58

В качестве расширения для решения Unix для DOS от Jonathan Leffler для безопасного преобразования в DOS, когда вы не уверены в текущих окончаниях строки файла:

sed '/^M$/! s/$/^M/'

Это проверяет, что линия еще не заканчивается в CRLF перед преобразованием в CRLF.

0
ответ дан 15 August 2018 в 15:52

В Linux легко преобразовать ^ M (ctrl-M) в * nix newlines (^ J) с sed.

В CLI будет что-то вроде этого, на самом деле будет разрыв строки в тексте. Тем не менее, \ передает, что ^ J вместе с sed:

sed 's/^M/\
/g' < ffmpeg.log > new.log

Вы получаете это, используя ^ V (ctrl-V), ^ M (ctrl-M) и \ (обратная косая черта) по мере ввода :

sed 's/^V^M/\^V^J/g' < ffmpeg.log > new.log
0
ответ дан 15 August 2018 в 15:52

Решения, опубликованные до сих пор, касаются только части проблемы, конвертируя DOS / Windows CRLF в LF Unix; часть, которую им не хватает, заключается в том, что DOS использует CRLF в качестве разделителя строк, а Unix использует LF в качестве терминатора линии. Разница в том, что файл DOS (обычно) не будет иметь ничего после последней строки в файле, в то время как Unix будет. Чтобы правильно выполнить преобразование, вам нужно добавить этот финальный LF (если только файл не имеет нулевой длины, то есть вообще не имеет линий). Мое любимое заклинание для этого (с небольшой добавленной логикой для обработки файлов в формате CR, разделенных в стиле Mac, а не для файлов досье, которые уже есть в unix-формате) немного Perl:

perl -pe 'if ( s/\r\n?/\n/g ) { $f=1 }; if ( $f || ! $m ) { s/([^\n])\z/$1\n/ }; $m=1' PCfile.txt

Примечание. что это отправляет Unixified версию файла в stdout. Если вы хотите заменить файл Unixified, добавьте флаг -i perl.

262
ответ дан 15 August 2018 в 15:52
  • 1
    используя tr -d '\015' <DOS-file >UNIX-file, где DOS-file == UNIX-file просто приводит к пустому файлу. К сожалению, выходной файл должен быть другим. – Buttle Butkus 15 November 2013 в 07:50
  • 2
    @ButtleButkus: Ну, да; поэтому я использовал два разных имени. Если вы заблокируете входной файл до того, как программа все это прочитает, как и при повторном использовании одного и того же имени, вы получите пустой файл. Это единообразное поведение в Unix-подобных системах. Для этого требуется специальный код для безопасного перезаписи входного файла. Следуйте инструкциям, и все будет в порядке. – Jonathan Leffler 15 November 2013 в 07:56
  • 3
    Кажется, я помню, что где-то в файле-заменителе. – Buttle Butkus 15 November 2013 в 08:08
  • 4
    Есть места; вы должны знать, где их найти. В пределах ограничений работает опция GNU sed -i (для работы на месте); ограничения связаны с файлами и символическими ссылками. Команда sort имеет «всегда» (с 1979 года, если не раньше) поддерживала опцию -o, которая может отображать один из входных файлов. Тем не менее, это отчасти потому, что sort должен прочитать все свои данные, прежде чем он сможет написать любой из своих результатов. Другие программы спорадически поддерживают перезапись одного из своих входных файлов. Вы можете найти программу общего назначения (сценарий), чтобы избежать проблем в «Среда программирования UNIX» от Kernighan & amp; Пайк. – Jonathan Leffler 15 November 2013 в 08:14
  • 5
    Спасибо, третий вариант. Я использовал параметр -i: sed -i $'s/\r$//' filename - для редактирования на месте. Я работаю над машиной, у которой нет доступа к Интернету, поэтому установка программного обеспечения является проблемой. – Warren Dew 24 November 2014 в 21:40
  • 6
    RIP мой файл данных. пошло не так, где-то xD – Ludovic Zenohate Lagouardette 21 January 2016 в 14:53
  • 7
    @LudovicZenohateLagouardette Был ли это обычный текстовый файл (т. Е. Csv или текст с разделителями табуляции) или что-то еще? Если бы это было в некотором формате базы данных, то манипулирование им, как если бы это был текст, скорее всего, повредит его внутреннюю структуру. – Gordon Davisson 24 January 2016 в 00:53
  • 8
    Обычный текст csv, но я думаю, что приложение было странным. Из-за этого мне кажется, что это испортило. Однако не беспокойтесь. Я всегда собираю резервные копии, это был даже не настоящий набор данных, а всего 1 гб. Реальный - 26 гб. – Ludovic Zenohate Lagouardette 24 January 2016 в 12:02

Есть много ответов awk / sed / etc, так как дополнение (поскольку это один из лучших результатов поиска для этой проблемы):

Возможно, у вас нет dos2unix, но у вас есть значок?

iconv -f UTF-16LE -t UTF-8 [filename.txt]
-f from format type
-t to format type

Или все файлы в каталоге:

find . -name "*.sql" -exec iconv -f UTF-16LE -t UTF-8 {} -o ./{} \;

Выполняет ту же самую команду для всех файлов .sql в текущей папке. -o - это выходной каталог, поэтому вы можете заменить его текущими файлами или, по соображениям безопасности / резервного копирования, выводить в отдельный каталог.

-4
ответ дан 15 August 2018 в 15:52
  • 1
    Это пытается добиться преобразования кодировки из UTF-16LE в UTF-8, но это не касается окончания строки. Это не имеет никакого отношения к заданному вопросу. – Palec 13 October 2017 в 16:36
  • 2
    Виноват. Я проверю это, но я только что использовал THAT DAY, чтобы исправить мою проблему grep, не выполняющуюся на моих файлах, потому что они были отформатированы в Windows. – Katastic Voyage 14 October 2017 в 20:34
  • 3
    Это также общая проблема, но не проблема, о которой спрашивает OP (и довольно много реже, чем проблема CRLF). – tripleee 27 October 2017 в 11:22

Вы можете использовать awk. Установите разделитель записи (RS) в регулярное выражение, которое соответствует всем возможным символам новой строки или символам. И установите разделитель выходной записи (ORS) в символ новой строки в стиле unix.

awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt
1
ответ дан 15 August 2018 в 15:52
  • 1
    Это тот, который работал для меня (MacOS, git diff показывает ^ M, отредактированный в vim) – Dorian 1 March 2017 в 13:17

TIMTOWTDI!

perl -pe 's/\r\n/\n/; s/([^\n])\z/$1\n/ if eof' PCfile.txt

На основе @GordonDavisson

Нужно рассмотреть возможность [noeol] ...

2
ответ дан 15 August 2018 в 15:52

Я попробовал sed 's / ^ M $ //' file.txt на OSX, а также несколько других методов (http://www.thingy-ma-jig.co.uk/blog/25-11-2010 / fixing-dos-line-endings или http://hintsforums.macworld.com/archive/index.php/t-125.html). Ничего не работало, файл остался без изменений (для воспроизведения ^ М) потребовалось ввести бит-в-В. В конце я использовал TextWrangler. Это не строго командная строка, но она работает, и она не жалуется.

-3
ответ дан 15 August 2018 в 15:52

Еще более простое awk-решение без программы:

awk -v ORS='\r\n' '1' unix.txt > dos.txt

Технически «1» - ваша программа, b / c awk требует один, когда задан параметр.

UPDATE: после повторного просмотра этой страницы в первый раз за долгое время я понял, что никто еще не опубликовал внутреннее решение, поэтому вот один из них:

while IFS= read -r line;
do printf '%s\n' "${line%$'\r'}";
done < dos.txt > unix.txt
6
ответ дан 15 August 2018 в 15:52
  • 1
    Это удобно, но только для того, чтобы быть ясным: это переводит Unix - & gt; Windows / DOS, который является противоположным направлением того, что требовал OP. – mklement0 28 February 2015 в 10:01
  • 2
    Это было сделано специально, оставлено в качестве упражнения для автора. eyerolls awk -v RS='\r\n' '1' dos.txt > unix.txt – nawK 1 March 2015 в 08:14
  • 3
    Великий (и слава вам за педагогическую утонченность). – mklement0 1 March 2015 в 08:35
  • 4
    «b / c awk требует один, когда предоставляется опция». - awk всегда требуется программа, независимо от того, указаны ли параметры или нет. – mklement0 1 March 2015 в 08:37
  • 5
    Чистое решение bash интересно, но гораздо медленнее, чем эквивалентное решение awk или sed. Кроме того, вы должны использовать while IFS= read -r line для точного сохранения входных строк, в противном случае обрезаются ведущие и конечные пробелы (альтернативно, не используйте имя переменной в команде read и работайте с $REPLY). – mklement0 1 March 2015 в 10:14

Эта проблема может быть решена стандартными инструментами, но для неосторожных достаточно много ловушек, которые я рекомендую вам установить команду flip, которая была написана более 20 лет назад Рахулом Деси, автором zoo. Это отличная работа, конвертирующая форматы файлов, в то время как, например, избегая случайного уничтожения двоичных файлов, что слишком легко, если вы просто участвуете в изменении каждого CRLF, который вы видите ...

18
ответ дан 15 August 2018 в 15:52
  • 1
    Любой способ сделать это потоковым способом, не изменяя исходный файл? – augurar 8 December 2013 в 04:08
  • 2
    @augurar вы можете проверить "похожие пакеты" [D0] packages.debian.org/wheezy/flip – n611x007 19 August 2014 в 16:12

Это сработало для меня

tr "\r" "\n" < sampledata.csv > sampledata2.csv 
3
ответ дан 15 August 2018 в 15:52
  • 1
    Это преобразует каждую одиночную DOS-новую строку в две строки UNIX. – Melebius 4 August 2015 в 09:11

Выполнение этого с помощью POSIX сложно:

POSIX Sed не поддерживает \r или \15. Даже если это так, опция -i на месте не является POSIX POSIX Awk поддерживает \r и \15, однако параметр -i inplace не POSIX d2u, а dos2unix не являются утилитами POSIX, но ex - это POSIX ex. не поддерживает \r, \15, \n или \12

Чтобы удалить возврат каретки:

ex -bsc '%!awk "{sub(/\r/,\"\")}1"' -cx file

Чтобы добавить возврат каретки:

ex -bsc '%!awk "{sub(/$/,\"\r\")}1"' -cx file
35
ответ дан 15 August 2018 в 15:52
  • 1
    Похоже, POSIX tr поддерживает \r. Таким образом, вы также можете использовать printf '%s\n' '%!tr -d "\r"' x | ex file (хотя предоставлено, это удалено \r, даже если оно не сразу предшествует \n). Кроме того, опция -b для ex не указана POSIX. – Wildcard 28 February 2017 в 05:50
  • 2
    Сделать это в POSIX легко. Вставьте литерал CR в скрипт, набрав его (это control-M). – Joshua 18 July 2018 в 03:41

Super duper easy with PCRE;

Как скрипт или замените $@ вашими файлами.

#!/usr/bin/env bash
perl -pi -e 's/\r\n/\n/g' -- $@
Это перезапишет ваши файлы на месте! Я рекомендую делать это только с помощью резервного копирования (контроль версий или иначе)
6
ответ дан 15 August 2018 в 15:52
  • 1
    Спасибо! Это работает, хотя я пишу имя файла и нет --. Я выбрал это решение, потому что его легко понять и адаптировать для меня. FYI, это то, что делают коммутаторы: -p принимают значение «while input» loop, -i редактировать входной файл на месте, -e выполнить следующую команду – Rolf 11 October 2017 в 15:21
  • 2
    Строго говоря, PCRE - это повторное использование движка регулярных выражений Perl, а не регулярное выражение Perl. У них обоих есть такая возможность, хотя есть и различия, несмотря на то, что это имя было названо. – tripleee 27 October 2017 в 11:24

интересно в моем git-bash на windows sed "" уже сделал трюк:

$ echo -e "abc\r" >tst.txt
$ file tst.txt
tst.txt: ASCII text, with CRLF line terminators
$ sed -i "" tst.txt
$ file tst.txt
tst.txt: ASCII text

Мое предположение заключается в том, что sed игнорирует их при чтении строк со входа и всегда записывает окончание строк Unix на выходе.

4
ответ дан 15 August 2018 в 15:52

Хотелось только подумать об этом же вопросе (на стороне Windows, но в равной степени применимом к linux.) Удивительно, что никто не упомянул очень автоматизированный способ преобразования CRLF & lt; -> LF для текстовых файлов с использованием старой доброй опции zip -ll (Info-ZIP):

zip -ll textfiles-lf.zip files-with-crlf-eol.*
unzip textfiles-lf.zip 

ПРИМЕЧАНИЕ: это создало бы zip-файл, сохраняющий исходные имена файлов, но преобразовывая окончания строки в LF. Затем unzip будет извлекать файлы как zip'ed, то есть с их исходными именами (но с LF-окончаниями), тем самым предлагая перезаписать локальные исходные файлы, если они есть.

Соответствующая выдержка из zip --help:

zip --help
...
-l   convert LF to CR LF (-ll CR LF to LF)
0
ответ дан 15 August 2018 в 15:52

Другие вопросы по тегам:

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