Bash 스크립트에서 DOS / Windows 줄 바꿈 (CRLF)을 Unix 줄 바꿈 (LF)으로 변환하는 방법?


336

프로그래밍 방식으로 (예 :을 사용하지 않음 vi) DOS / Windows 줄 바꿈을 Unix로 변환하려면 어떻게해야합니까?

dos2unixunix2dos명령은 특정 시스템에서 사용할 수 없습니다. sed/ awk/ tr? 와 같은 명령을 사용하여이를 에뮬레이션하는 방법


9
일반적으로 dos2unix패키지 관리자를 사용하여 설치 하면 훨씬 간단하고 대부분의 플랫폼에 존재합니다.
Brad Koch

1
동의했다! Mac OSX에서 '브래드 설치 dos2unix'로 간단한 @BradKoch
SmileIT

답변:


322

trDOS에서 Unix로 변환 하는 데 사용할 수 있습니다 . 그러나 CR이 파일에 CRLF 바이트 쌍의 첫 번째 바이트로만 나타나는 경우에만이 작업을 안전하게 수행 할 수 있습니다. 이것은 일반적으로 그렇습니다. 그런 다음 다음을 사용하십시오.

tr -d '\015' <DOS-file >UNIX-file

이름 DOS-file은 이름 과 다릅니다 UNIX-file. 같은 이름을 두 번 사용하려고하면 파일에 데이터가 없게됩니다.

다른 방법으로 (표준 'tr'로) 수행 할 수 없습니다.

캐리지 입력 방법을 알고 있으면 스크립트로 리턴하십시오 ( control-V, control-Mcontrol-M 입력).

sed 's/^M$//'     # DOS to Unix
sed 's/$/^M/'     # Unix to DOS

여기서 '^ M'은 control-M 문자입니다. bash ANSI-C Quoting 메커니즘을 사용하여 캐리지 리턴을 지정할 수도 있습니다 .

sed $'s/\r$//'     # DOS to Unix
sed $'s/$/\r/'     # Unix to DOS

그러나이 작업을 매우 자주 수행해야하는 경우 (대략 말하면) 변환 프로그램 (예 : dos2unixunix2dos, 또는 아마도 dtouutod) 을 설치하고 사용하는 것이 훨씬 합리적 입니다.

전체 디렉토리 및 서브 디렉토리를 처리해야하는 경우 다음을 사용할 수 있습니다 zip.

zip -r -ll zipfile.zip somedir/
unzip zipfile.zip

줄 끝이 CRLF에서 CR로 변경된 zip 아카이브가 생성됩니다. unzip그런 다음 변환 된 파일을 다시 제자리에 넣습니다 (파일별로 파일 요청-예 : 모두에게 대답 할 수 있음). 이것을 지적 해 준 @vmsnomad에게 감사의 말을 전한다.


9
tr -d '\015' <DOS-file >UNIX-filewhere DOS-file==를 사용 UNIX-file하면 빈 파일이 생성됩니다. 불행하게도 출력 파일은 다른 파일이어야합니다.
Buttle Butkus

3
@ButtleButkus : 글쎄요. 그래서 두 개의 다른 이름을 사용했습니다. 프로그램이 모든 것을 읽기 전에 입력 파일을 zap하면 동일한 이름을 두 번 사용할 때 빈 파일이 생깁니다. 이것은 유닉스 계열 시스템에서 균일 한 동작입니다. 입력 파일 덮어 쓰기를 안전하게 처리하려면 특수 코드가 필요합니다. 지시를 따르십시오. 그러면 정상입니다.
Jonathan Leffler

파일 내 검색 대체 기능을 기억하는 것 같습니다.
Buttle Butkus

4
장소가 있습니다. 어디서 찾을 수 있는지 알아야합니다. 한도 내에서 GNU sed옵션 -i(현재 위치 용)이 작동합니다. 제한은 링크 된 파일과 심볼릭 링크입니다. 이 sort명령은 'always'(이전이 아닌 경우 1979 년 이후) -o에서 입력 파일 중 하나를 나열 할 수 있는 옵션을 지원했습니다 . 그러나 일부 sort는 출력을 쓰기 전에 모든 입력을 읽어야하기 때문입니다. 다른 프로그램은 입력 파일 중 하나를 덮어 쓰는 것을 산발적으로 지원합니다. Kernighan & Pike의 'UNIX Programming Environment' 에서 문제를 피하기위한 범용 프로그램 (스크립트)을 찾을 수 있습니다 .
Jonathan Leffler

3
세 번째 옵션은 저에게 효과적이었습니다. 감사합니다. -i 옵션을 사용했습니다 : sed -i $'s/\r$//' filename-제자리에서 편집하십시오. 인터넷에 액세스 할 수없는 컴퓨터에서 작업 중이므로 소프트웨어 설치에 문제가 있습니다.
Warren Dew

64
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

사용 sed -i에 적절한 변환 예에 sed -i 's/..../' file.


10
내 파일 만했기 때문에 나는 변형을 사용 \r:tr "\r" "\n" < infile > outfile
매트 토드

1
@MattTodd 답변으로 게시 할 수 있습니까? 이 -d더 자주 표시되며 "전용 \r"상황 에서는 도움이되지 않습니다 .
n611x007

5
제안 된 것을 참고 \r\n매핑 두 번 간격 파일의 효과가있다; DOS로 끝나는 각 단일 CRLF 행 \n\n은 Unix로됩니다.
Jonathan Leffler

재귀 적으로 이것을 할 수 있습니까?
Aaron Franke

36

POSIX로 이것을하는 것은 까다 롭습니다 :

  • POSIX Sed\r또는을 지원하지 않습니다 \15. 그랬더라도 in place 옵션 -i은 POSIX가 아닙니다.

  • POSIX Awk\r및을 지원 \15하지만 -i inplace옵션은 POSIX가 아닙니다.

  • d2udos2unixPOSIX 유틸리티 가 아니지만 ex

  • POSIX 전은 지원하지 않습니다 \r, \15, \n또는\12

캐리지 리턴을 제거하려면 다음을 수행하십시오.

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

캐리지 리턴을 추가하려면 다음을 수행하십시오.

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

2
POSIX가 tr지원하는\r 것처럼 보입니다 . 그래서 당신은 또한 사용할 수 있습니다 printf '%s\n' '%!tr -d "\r"' x | ex file(물론, \r바로 앞 이 아니더라도 제거되었습니다 \n). 또한 POSIX 에서 -b옵션을 ex지정하지 않았습니다.
와일드 카드

1
POSIX에서이 작업을 수행하는 것은 쉽습니다. 스크립트에 CR 리터럴을 입력하여 포함시킵니다 (control-M).
Joshua

28

-c {command} 옵션으로 프로그래밍 방식으로 vim을 사용할 수 있습니다.

유닉스에 할 일 :

vim file.txt -c "set ff=unix" -c ":wq"

유닉스 할일 :

vim file.txt -c "set ff=dos" -c ":wq"

"set ff = unix / dos"는 파일의 파일 형식 (ff)을 Unix / DOS 줄 끝 형식으로 변경하는 것을 의미합니다

": wq"는 파일을 디스크에 쓰고 편집기를 종료 함을 의미합니다 (루프에서 명령을 사용할 수 있음)


3
이것은 가장 우아한 솔루션처럼 보였지만 wq의 의미에 대한 설명이 부족합니다.
Jorrick Sleijster

5
사용하는 사람 vi은 무엇을 :wq의미 하는지 알게 될 것 입니다. 3자가 아닌 사람들은 1) vi 명령 영역 열기, 2) 쓰기 및 3) 종료를 의미합니다.
David Newcomb

CLI에서 vim에 대화식으로 명령을 추가 할 수있을 줄은
몰랐습니다

": wq"대신 ": x"를 사용할 수 있습니다.
JosephConrad

25

AWK를 사용하면 다음을 수행 할 수 있습니다.

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

Perl을 사용하면 다음을 수행 할 수 있습니다.

perl -pe 's/\r$//' < dos.txt > unix.txt

2
좋은 휴대용 awk 솔루션.
mklement0

23

파일을 제자리에서 변환하려면

dos2unix <filename>

변환 된 텍스트를 다른 파일로 출력하려면

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

우분투 또는 데비안에서 설치할 수 있습니다

sudo apt install dos2unix

또는 homebrew를 사용하는 macOS

brew install dos2unix

1
질문에 dos2unix의 대안이 필요하다는 것을 알고 있지만 첫 번째 Google 결과입니다.
보리스

18

이 문제는 표준 도구를 사용하여 해결할 수 있지만 flip20 년 전에 필자 인 Rahul Dhesi가 작성한 명령 을 설치하는 것이 좋습니다 zoo. 예를 들어 바이너리 파일이 실수로 파괴되는 것을 피하면서 파일 형식을 변환하는 훌륭한 작업을 수행합니다.


원본 파일을 수정하지 않고 스트리밍 방식으로이 작업을 수행 할 수있는 방법이 있습니까?
augurar

@augurar 당신은 "유사한 패키지"를 확인할 수 있습니다 packages.debian.org/wheezy/flip
n611x007

texxto를 잘못된 플래그로 실행하여 OS의 절반을 깨는 경험이있었습니다. 전체 폴더에서 수행하려는 경우 특히주의하십시오.
A_P

14

지금까지 게시 된 솔루션은 문제의 일부만 처리하여 DOS / Windows의 CRLF를 Unix의 LF로 변환합니다. 그들이 누락 된 부분은 DOS가 CRLF를 줄 구분자로 사용하는 반면 Unix는 LF를 줄 종결 자로 사용한다는 것 입니다. 차이점은 DOS 파일 (일반적으로)은 파일의 마지막 줄 뒤에 아무것도 없지만 Unix는 그렇지 않습니다. 변환을 올바르게 수행하려면 최종 LF를 추가해야합니다 (파일의 길이가 0이 아닌 경우 (예 : 전혀 줄이없는 경우)). 내가 가장 좋아하는 incantation (맥 스타일의 CR 분리 파일을 처리하는 논리가 추가되어 있으며 이미 유닉스 형식 인 가장 성가신 파일은 아닙니다)은 약간 펄입니다.

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 버전으로 바꾸려면 perl의 -i플래그를 추가하십시오 .


@LudovicZenohateLagouardette 일반 텍스트 파일 (예 : csv 또는 tab-demited text)입니까, 아니면 다른 것입니까? 데이터베이스 형식 인 경우 텍스트처럼 조작하면 내부 구조가 손상 될 가능성이 큽니다.
Gordon Davisson

평범한 텍스트 CSV, 그러나 나는 enconding이 이상하다고 생각합니다. 그 때문에 엉망이라고 생각합니다. 그러나 걱정하지 마십시오. 나는 항상 백업을 수집하고 있습니다. 이것은 실제 데이터 세트가 아니라 1GB입니다. 실제는 26GB입니다.
Ludovic Zenohate Lagouardette

14

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))

수퍼 유저 로부터 교차 게시되었습니다 .


1
사용법이 잘못되었습니다. real 은 기본적으로 모든 입력 파일을 dos2unix변환 합니다 . 사용법은 -n매개 변수를 의미합니다 . 그리고 실제 dos2unix는 파일을 제공하지 않으면 stdin에서 읽고 stdout에 쓰는 필터입니다.
jfs

8

PCRE로 쉽게 슈퍼 듀퍼;

스크립트로 사용하거나 $@파일로 교체 하십시오.

#!/usr/bin/env bash
perl -pi -e 's/\r\n/\n/g' -- $@

파일을 덮어 씁니다!

백업 (버전 제어 또는 기타)으로 만 수행하는 것이 좋습니다.


감사합니다! 파일 이름을 쓰고 있지만 no 작동하지만 작동합니다 --. 이해하고 적응하기 쉽기 때문에이 솔루션을 선택했습니다. 참고로, 이것은 스위치가하는 일입니다 : -p"while input"루프를 가정하고, -i입력 파일을 제자리에 편집하고, -e다음 명령을 실행하십시오
Rolf

엄밀히 말하면 PCRE는 Perl의 정규식 엔진이 아닌 Perl의 정규식 엔진을 다시 구현 한 것입니다. 이름에도 불구하고 차이점이 있지만 둘 다이 기능을 가지고 있습니다.
tripleee

6

프로그램이없는 더 간단한 awk 솔루션 :

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

기술적으로 '1'은 귀하의 프로그램이며 b / c awk는 옵션이 주어질 때 하나를 요구합니다.

업데이트 : 오랫동안이 페이지를 처음 방문한 후에 아무도 내부 솔루션을 아직 게시하지 않았다는 것을 깨달았습니다.

while IFS= read -r line;
do printf '%s\n' "${line%$'\r'}";
done < dos.txt > unix.txt

편리하지만 분명합니다. 이것은 유닉스-> Windows / DOS를 번역합니다. 이것은 OP가 요청한 것과 반대 방향 입니다.
mklement0

5
그것은 의도적으로 이루어졌으며 저자의 연습으로 남았습니다. eyerolls awk -v RS='\r\n' '1' dos.txt > unix.txt
nawK

훌륭합니다. (교육학적인 문제에 대한 여러분의 의견).
mklement0

1
"b / c awk는 옵션이 주어지면 하나 필요합니다." -awk 옵션 지정 여부에 관계없이 항상 프로그램이 필요합니다.
mklement0

1
순수한 bash 솔루션은 흥미롭지 만 동등한 솔루션 awk이나 sed솔루션 보다 훨씬 느립니다 . 또한 while IFS= read -r line입력 줄을 충실하게 보존 하기 위해 사용해야합니다 . 그렇지 않으면 선행 및 후행 공백이 read$REPLY립니다 ( 또는 명령에 변수 이름을 사용하지 않고 작업 ).
mklement0

5

똑같은 질문 (Windows 측에서도 Linux에도 동일하게 적용 가능)을 숙고해야했습니다. 아마도 아무도 좋은 이전 zip -ll옵션 (Info-ZIP)을 사용하여 텍스트 파일에 대해 CRLF <-> LF 변환을 수행하는 자동화 된 방법을 언급하지 않았습니다 .

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

참고 : 이렇게하면 원래 파일 이름은 유지하지만 줄 끝은 LF로 변환되는 zip 파일이 만들어집니다. 그런 다음 unzip압축을 푼 파일, 즉 원래 이름 (LF 끝)을 사용하여 로컬 원본 파일을 덮어 쓸지 묻는 메시지가 표시됩니다.

의 관련 발췌 zip --help:

zip --help
...
-l   convert LF to CR LF (-ll CR LF to LF)

나에 따르면 전체 디렉토리와 하위 디렉토리를 처리 할 수 ​​있으므로 가장 좋은 대답입니다. 나는 그것을 아래로 파고 다행입니다.
caram

5

흥미롭게도 Windows의 git-bash에서 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는 입력에서 줄을 읽을 때 무시하고 항상 출력에 유닉스 줄 끝을 씁니다.


4

이것은 나를 위해 일했다

tr "\r" "\n" < sampledata.csv > sampledata2.csv 

9
이것은 모든 단일 DOS 줄 바꿈을 두 개의 UNIX 줄 바꿈으로 변환합니다 .
Melebius

2

Homebrew가 설치된 경우 Mac OSX의 경우 [ http://brew.sh/][1]

brew install dos2unix

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

이 명령으로 파일을 수정하므로 파일 사본을 작성했는지 확인하십시오. -c mac 옵션은 스위치가 osx와 호환되도록합니다.


이 답변은 실제로 원래 포스터의 질문이 아닙니다.
hlin117

2
OS X 사용자는 -c macOS 이전 X CR전용 줄 바꿈 을 변환하는 데 사용하지 않아야합니다 . 이 모드는 Mac OS 9 이전 또는 이전의 파일에 대해서만 사용하려고합니다.
askewchan

2

TIMTOWTDI!

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

@GordonDavisson 기반

우리는 가능성을 고려해야합니다 [noeol]...


2

awk를 사용할 수 있습니다. 레코드 구분 기호 ( RS)를 가능한 모든 줄 바꿈 문자와 일치하는 정규 표현식으로 설정하십시오 . 그리고 출력 레코드 구분 기호 ( ORS)를 유닉스 스타일 개행 문자로 설정하십시오.

awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt

그것은 나를 위해 일한 것입니다 (MacOS, git diff^ M 표시, vim에서 편집 됨)
Dorian

2

Linux에서는 sed를 사용하여 ^ M (ctrl-M)을 * nix 줄 바꿈 (^ J)으로 쉽게 변환 할 수 있습니다.

CLI에서 이와 같이 표시되며 실제로 텍스트에 줄 바꿈이 있습니다. 그러나 \는 sed에 ^ J를 전달합니다.

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

2
sed --expression='s/\r\n/\n/g'

질문에 sed가 언급되었으므로 sed를 사용하여이를 달성하는 가장 직접적인 방법입니다. 표현에 따르면 캐리지 리턴과 줄 바꿈을 모두 줄 바꿈만으로 바꿉니다. 이것이 Windows에서 Unix로 갈 때 필요한 것입니다. 작동하는지 확인했습니다.


John Paul--이 답변은 삭제 된 것으로 표시되어 검토 대기열에 나왔습니다. 일반적으로 22 세의 답변이있는 8 살짜리와 같은 질문이있는 경우 기존 답변이 다른 방식으로 답변이 유용한 방법을 설명하고 싶을 것입니다.
zzxyz

0

파일의 현재 줄 끝이 확실하지 않은 경우 Jonathan Leffler의 Unix to DOS 솔루션의 확장으로 DOS로 안전하게 변환 할 수 있습니다.

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

CRLF로 변환하기 전에 행이 CRLF로 끝나지 않았는지 확인합니다.


0

허용 된 답변을 기반으로 스크립트를 만들었으므로 결국 추가 파일이 필요없고 나중에 제거하고 이름을 바꾸지 않고도 직접 변환 할 수 있습니다.

convert-crlf-to-lf() {
    file="$1"
    tr -d '\015' <"$file" >"$file"2
    rm -rf "$file"
    mv "$file"2 "$file"
}

"file1.txt2"가 이미 존재하지 않거나 덮어 쓰여질 "file1.txt"와 같은 파일이 있는지 확인하십시오. 파일을 저장할 임시 장소로 사용합니다.


0

bash 4.2 이상에서는 다음과 같은 것을 사용하여 bash 내장 만 사용하는 후행 CR을 제거 할 수 있습니다.

if [[ "${str: -1}" == $'\r' ]]; then
    str="${str:: -1}"
fi

-3

OSX에서 sed 's / ^ M $ //'file.txt와 여러 가지 다른 방법을 시도했습니다 ( 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 ). 아무것도 작동하지 않고 파일은 변경되지 않은 상태로 남아 있습니다 (^ M을 재현하려면 Ctrl-v Enter가 필요함). 결국 나는 TextWrangler를 사용했습니다. 그것은 엄격하게 명령 줄이 아니지만 작동하며 불평하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.