[Bash] Windows에서 작성된 파일 개행 문자 문제 해결

2023. 10. 20. 11:02Developers 공간 [Shorts]/Software Basic

728x90
반응형
<분류>
A. 수단
- OS/Platform/Tool : Linux, Kubernetes(k8s), Docker, AWS
- Package Manager : node.js, yarn, brew, 
- Compiler/Transpillar : React, Nvcc, gcc/g++, Babel, Flutter

- Module Bundler  : React, Webpack, Parcel

B. 언어
- C/C++, python, Javacsript, Typescript, Go-Lang, CUDA, Dart, HTML/CSS

C. 라이브러리 및 프레임워크 및 SDK
- OpenCV, OpenCL, FastAPI, PyTorch, Tensorflow, Nsight

 


1. What? (현상)

Window 에서 작업을 했던 파일을 Ubuntu로 가져와 작업을 하려고 하니, 실행이 안되는 문제가 있습니다.

 

이럴 때 나오는 에러는 아래와 같습니다.

-bash: ./my_script.sh: /bin/bsh^M: bad interpreter: No such file or directory

 

원인과 해결책을 살펴보고자 합니다.


2. Why? (원인)

 

OS별로 개행문자의 종류는 아래와 같이 다릅니다. 

 

  • Unix 계열 : LF
    ** LF(Line Feed) : \n
  • OS X : Mac OS X 버전은 CR, 이후는 LF
    ** CR(Carriage Return) : \r
  • Windows : CRLF
    ** CRLF( CR+ LF ) : \r\n

 

이런 OS 사이트에 데이터를 전송할 때 FTP(File Transfer Protocol)을 사용하면 아래와 같은 여러가지 Mode를 선택할 수 있습니다. 이때 개행 문자가 어떻게 변환 되는지 예로 살펴보겠습니다.

  • ASCII 모드 : 텍스트 파일을 전송하는 것에 적합하며, CR과 LF가 각각의 대응되는 0x0D와 0x0A 문자로 변환되어 ASCII 형태로 전송됩니다.
  • Binary 모드 : 이미지, 오디오, 비디오 등 바이너리 파일을 전송하는 것에 적합하며, Byte단위로 전송됩니다. 

 

따라서, OS 간에 파일을 옮기는 경우, 알아서 개행문자가 변환되지 않으므로 CR,LF,CRLF 미리 구분해 변환해주는 것이 좋겠습니다.

더보기

-----------------------------------------------------------------------------

<Text Encoding 방법>

1.  ASCII(American Standard Code for Information Interchange)

128개의 문자 조합에 대해 7 bits로 표현하는 방법입니다. ASCII 코드는 언어에 있어서는 영어만 표현할 수 있으며, 현재는 대부분 사용되지 않습니다.

[ASCII 코드 표]

2. Unicode

전세계 각각의 언어를 모두 표현하기 위해 나왔으며, 65,536개의 문자를 16bits로 표현합니다. 하지만 역시나 범위가 한정되어 있고, 다국어 환경에서 서로 호환되지 않는 문제점이 있습니다. 

 

3. UTF-8(Universal Coded Character Set + Transformation Format 8-bit)

 

Unicode 한문자를 나타내기 위해 1Bytes(8bits) ~ 4Bytes(32bits)를 가변적으로 사용하게 됩니다. 즉, 기존에 적은 수의 비트로 표현이 가능한 것은 적게 표현하고, 많이 필요한 것은 많은 비트를 활용해 표현하기 위해 고안되었습니다. 하나의 8bits 덩어리를 Octet이라고 부르며 아래 그림과 같이 표현합니다.

** UTF-16의 경우 16bit로 된 Unicode 변환 방식입니다.

[UTF-8 예시]

모든 ASCII는 앞서 본 바와 같이 8bits로 표현할 수 있기 때문에 영어를 활용하는 경우 다른 문자를 활용하는 것보다 더 적은 메모리로 문자를 Encoding할 수 있습니다. 또한 영어/숫자/기호는 8bits로, 한글/한자는 3Bytes(24bits)로 표현하기 때문에 한글/한자는 ASCII와는 호환이 어려운 것을 알 수 있습니다.

-----------------------------------------------------------------------------


3. How? (해결책)

먼저 vim을 활용하는 경우 아래와 같이 들어가 Binary 모드로 내용을 들어가 개행 모드를 확인 할 수 있습니다.

vim -b File_Name

아래는 윈도우에서 작성된 파일Ubuntu에서 열었을 때의 예시입니다.

1 This^M
2 is^M
3 for^M
3 checking^M

위의 ^M은 CR(\r)과 같습니다. Ubuntu에서 윈도우에서 받은 파일의 \r을 모두 없애기 위해서 sed라는 명령어를 활용해보겠습니다. sed(Streamline EDitor)는 텍스트를 필터링하거나 변환하는 스트림 편집기입니다. 즉, 특정 패턴을 적용해 데이터를 표준 출력으로 보거나, 파일 자체를 변환할 때 사용합니다.

 

예를 들어, 아래와 같이 실행해 준다면 원본파일을 바꾸지는 않고 표준출력만 하게 됩니다. 

sed 's/Text_FROM/Text_TO/' File_Name

-i 옵션은 in-place라고 불리며, 원래는 위와 같이 원본영향을 안주는 명령어였는데, 이 옵션을 활용하면 원본을 바꿉니다. 따라서 아래와 같은 명령어를 통해 윈도우에서 작성된 파일을 Ubuntu에서 활용할 수 있도록 수정할 수 있습니다.

** The dollar sign ($) : end of the line을 의미하므로 써주는 것도 좋습니다.

# Delete hidden new line
sed -i 's/\r//' File_Name
sed -i 's/\r$//' File_Name

728x90
반응형