명령줄 (The Command Line)
이 장에서는 명령줄(command line)을 만나보고 사용법을 배울 것입니다. pixi add <packagename>과 같은 몇 가지 주요 명령어를 제외하면, 이 책의 나머지 부분을 따라가기 위해 명령줄 사용법을 반드시 알아야 하는 것은 아닙니다. 하지만 명령줄에 대한 아주 작은 지식이라도 코딩에서는 큰 도움이 되며 여러분에게 유용할 것입니다.
이 장의 명령어들을 여러분의 컴퓨터에서 직접 시도해 보려면, Visual Studio Code(맥 및 리눅스)의 메뉴 바에서 ’New Terminal’을 선택하거나, 윈도우의 경우 Linux용 Windows 하위 시스템(WSL) 또는 git bash를 사용하거나, 무료 온라인 터미널을 사용할 수 있습니다.
이 장은 Grant McDermott의 훌륭한 노트, Melanie Walsh의 Introduction to Cultural Analytics & Python, Data Science Bootstrap, calmcode.io, 그리고 Research Software Engineering with Python을 포함한 수많은 소스의 도움을 받았습니다. 집필 당시 아직 편집 중이었던 유망한 리소스로 Data Science at the Command Line이 있습니다.
명령줄이란 무엇인가요?
명령줄은 마우스로 탐색하는 그래픽 사용자 인터페이스(GUI)와 달리, 컴퓨터에 텍스트 기반 명령을 한 줄씩 직접 내리는 방법입니다. 쉘(shell), 배시(bash), 터미널(terminal), CLI, 명령줄 등 여러 이름으로 불립니다. 이것들은 실제로는 서로 다른 것들이지만, 대부분의 사람들은 대개 같은 의미로 사용합니다. 쉘은 여러분이 상호 작용하는 운영 체제의 일부이지만, 사람들은 보통 명령줄을 의미할 때 쉘이라는 단어를 씁니다. bash는 명령줄에서 사용되는 프로그래밍 언어로, 사실 ’Born Again SHell’의 약자입니다. 터미널은 맥에서 명령줄을 가리킬 때 가끔 사용됩니다. 마지막으로 CLI는 명령줄 인터페이스(command line interface)의 약자로, 애플리케이션의 문맥에서 자주 사용됩니다. 예를 들어, uv는 패키지를 설치하기 위해 명령줄에서 실행하므로(pixi add packagename) 명령줄 인터페이스를 가지고 있습니다.
UNIX 기반 시스템(MacOS 및 리눅스)과 윈도우 시스템의 명령줄 사이에는 큰 차이가 있다는 점을 언급할 가치가 있습니다. 여기서는 UNIX 버전만 다룰 것입니다. 윈도우에도 명령줄이 있지만 코딩용으로 널리 사용되지는 않습니다. 만약 윈도우 머신을 사용 중이라면, Linux용 Windows 하위 시스템을 사용하여 UNIX 명령줄에 접속할 수 있습니다.
명령줄은 왜 유용한가요?
명령줄은 용도가 다양합니다. 그래픽 사용자 인터페이스는 일반적으로 사용하기 조금 더 쉽지만, 반복 가능성이나 확장성이 떨어집니다. 명령줄은 텍스트 기반 지침을 사용하고 프로그래밍이 가능하기 때문에 반복 가능하고 확장 가능합니다. 이러한 속성들은 연구와 분석에 매우 유용합니다.
명령줄을 사용하여 지침을 내리는 포괄적인 이유는 다음과 같습니다:
소프트웨어 기능: 일부 소프트웨어는 오직 명령줄 인터페이스만 가지고 있습니다.
효율성: 컴퓨터의 메모리는 제한되어 있는데, 그래픽 사용자 인터페이스는 메모리를 많이 사용합니다. 명령줄은 더 적게 사용합니다.
재현성: 명령줄에서 실행되는 스크립트는 그래픽 사용자 인터페이스를 클릭하는 것과 달리 재현 가능합니다.
하드웨어 기능: 고성능 및 클라우드 컴퓨팅의 경우 명령줄이 유일한 방법인 경우가 많습니다.
자동화: 입력과 출력이 있는 여러 프로그램을 명령줄에서 실행되는 스크립트를 통해 순차적으로 실행할 수 있습니다.
다음은 명령줄을 사용하여 완료할 수 있는 몇 가지 구체적인 작업들입니다:
코드를 버전 관리 하에 두기
한 번의 명령으로 여러 파일의 이름 변경 및 이동하기
컴퓨터에서 파일 찾기
문서 유형 간 변환하기 (예: \(\LaTeX\) (.tex)에서 Word (.docx)로)
클라우드 리소스에 연결 및 사용하기
명령줄 사용하기
배시(Bash)는 UNIX의 기본 명령줄 쉘인 경우가 많지만, zsh가 인기를 얻어 현재 맥의 기본 쉘이 되었습니다. 무엇을 사용할지 고민 중이라면 oh-my-zsh의 zsh(Z Shell)를 추천합니다.
Visual Studio Code 내에서 명령줄을 열려면, 맥에서는 ⌃ + ` 단축키를, 윈도우/리눅스에서는 ctrl + `를 사용하거나 “View > Terminal”을 클릭하세요.
이제 다음과 같은 화면이 보일 것입니다.
username@hostname:~$이것이 무엇을 말해주는지 분석해 보겠습니다. username은 현재 사용자가 누구인지 알려줍니다. @hostname은 컴퓨터의 이름을 나타냅니다. ~는 기본(홈) 디렉토리입니다. 그리고 $는 ’명령 프롬프트’로, 여기에 명령어를 입력해야 한다는 신호입니다. (사용 중인 쉘이나 운영 체제에 따라 이 줄의 모습이 다를 수 있음에 유의하세요.)
간단한 명령어를 시도해 봅시다: 명령줄 창에 date를 입력하고 엔터를 누르세요. 오늘의 날짜와 시간(및 시간대)이 보일 것입니다. echo hello와 whoami도 시도해 볼 수 있습니다.
터미널에서 실행하는 모든 명령어는 동일한 구조를 가집니다: 명령어(command), 그 뒤에 옵션(option(s)), 그 뒤에 인수(argument(s)). 옵션은 플래그(flags)라고도 불립니다. 예제를 통해 이를 확인해 보겠습니다: ’data.csv’라는 CSV 파일이 포함된 디렉토리에서 터미널을 열었다면, 처음 5줄을 확인하는 명령어는 다음과 같습니다:
head -n 5 data.csv여기서 head는 파일의 시작 부분을 확인하는 명령어이고, -n은 옵션이며, 5는 파일의 5줄을 가져오기 위한 인수이고, data.csv는 마지막 인수인 파일 이름입니다.
위의 예제에서 -n과 같은 플래그나 옵션은 대개 대시 하나(-) 또는 가끔 대시 두 개(--)로 시작합니다. 이들은 함께 연결될 수도 있는데, 예를 들어 ls -la는 ls -a와 ls -l을 결합한 것입니다.
명령줄을 사용할 때 공백은 특별한 역할을 합니다. 이러한 이유로 파일 이름에 공백을 피하는 것이 좋은 습관입니다. 공백이 포함된 파일 이름을 참조해야 한다면, 따옴표를 사용하거나 `\`를 사용하여 공백을 이스케이프해야 합니다. 예를 들어 `this is my file.txt`는 `this\ is\ my\ file.txt`가 됩니다.
명령줄에서 프로그램을 실행하려면 명령어 자리에 프로그램의 이름을 쓰기만 하면 됩니다. 사실 명령어 자체가 프로그램입니다. date 명령어는 여러분의 컴퓨터에서 찾을 수 있는 실제 프로그램을 가리킵니다. 그리고 이는 명령줄에서 스크립트를 실행할 때 어떤 일이 일어나는지를 부분적으로 설명해 줍니다(이에 대해서는 나중에 더 자세히 다룹니다).
명령어를 몇 번 실행해 보면, 텍스트 파일이나 파이썬 스크립트처럼 명령줄 내에서 자유롭게 돌아다닐 수 없다는 점을 눈치채셨을 것입니다. 다음은 명령줄 탐색을 위한 몇 가지 팁입니다:
탭(tab) 키를 사용하여 부분적으로 작성된 명령어를 자동 완성하세요.
dat를 입력한 뒤 탭을 눌러 확인해 보세요.↑ 및 ↓ 키를 사용하여 이전 명령어들을 훑어보세요.
단어 전체를 건너뛰려면 맥에서는 ⌥ + → 및 ⌥ + ←를, 윈도우와 리눅스에서는 ctrl + → 및 ctrl + ←를 사용하세요.
ctrl + a를 누르면 커서가 줄의 시작 부분으로 이동합니다.
ctrl + e는 커서를 줄의 끝으로 이동시킵니다.
ctrl + k를 누르면 커서 오른쪽의 모든 내용이 삭제됩니다.
ctrl + u를 누르면 커서 왼쪽의 모든 내용이 삭제됩니다.
ctrl + r을 사용하여 이전에 사용한 명령어들을 검색하세요.
디렉토리 탐색하기
탐색에 대해 이야기하는 김에, 명령줄을 열었을 때 컴퓨터의 어디에 있는지 이해하는 것이 유용합니다. VS Code 내에서 터미널 패널을 열면 기본적으로 프로젝트와 동일한 폴더 내에서 시작하게 됩니다. VS Code 외부에서 터미널 인스턴스를 시작하면 컴퓨터의 루트 디렉토리에서 터미널이 열립니다. 예를 들어 맥에서 새 터미널 창을 열면 /Users/사용자이름/에서 시작합니다.
터미널을 열었을 때 “어디”에 있는지 확인하려면 “print working directory”의 약자인 pwd 명령어를 사용할 수 있습니다.
아래 표는 명령줄을 사용하여 컴퓨터 내에서 이동할 때 유용한 명령어들을 보여줍니다. cd는 현재 디렉토리를 기준으로 한 상대 경로를 받는다는 점에 유의하세요.
| 명령어 | 기능 |
|---|---|
pwd |
현재 디렉토리 표시 |
cd |
디렉토리 변경 명령어 |
cd .. |
상위 디렉토리로 한 단계 이동 (cd ../..는 두 단계) |
cd ~ |
홈 디렉토리로 이동 |
cd - |
이전 디렉토리로 이동 |
cd documents/papers |
’papers’라는 이름의 디렉토리로 직접 이동 |
명령줄에서 파이썬 사용하기
명령줄이 파이썬에 유용한 여러 가지 방법이 있습니다(이 방법들은 다른 언어에도 적용됩니다).
물론 패키지는 명령줄에서 설치됩니다. 예를 들어 (노트북 실행을 위한) Jupyter Lab을 설치하는 명령어는 다음과 같습니다.
pixi add jupyterlabanalysis.py라는 스크립트가 있다면, 명령줄에서 다음과 같이 파이썬으로 실행할 수 있습니다.
pixi run python analysis.py이는 파이썬을 프로그램으로 호출하고 analysis.py를 인수로 전달합니다. 만약 여러 버전의 파이썬을 가지고 있다면(프로젝트마다 별도의 버전을 사용하는 모범 사례를 따르고 있다면 그래야 합니다), 다음을 통해 어떤 파이썬 버전이 사용 중인지 확인할 수 있습니다.
which python터미널 유용 명령어
이제 터미널에서 유용한 명령어들을 살펴보겠습니다.
| 명령어 | 기능 |
|---|---|
man <command> |
주어진 명령어에 대한 매뉴얼 표시 |
touch <filename> |
<filename>이라는 이름의 빈 파일 생성 |
code <filename> |
VS Code에서 파일 열기 (파일이 없으면 생성) |
mkdir <foldername> |
foldername이라는 이름의 새 폴더 생성 |
echo <text> |
<text> 출력 |
cat <filename> |
<filename>의 전체 내용 출력 |
head <filename> |
파일의 시작 부분 출력 |
tail <filename> |
파일의 끝 부분 출력 |
> <filename> |
화면 출력을 <filename>으로 리다이렉션. 예: echo "Hello World" > hello.txt |
>> <filename> |
출력을 화면 대신 <filename>의 끝에 추가 (덮어쓰지 않음) |
| |
파이프 심볼: 한 명령어의 출력을 다른 명령어의 입력으로 사용. 예: head -n 10 data.csv | > hello_world.txt는 data.csv의 처음 10줄을 hello_world.txt 파일에 기록함 |
less <filename> |
파일 내용을 페이지 단위로 출력. ctrl+v와 Alt+v(맥은 ⌘+v와 ⌥+v)로 이동. q를 눌러 종료 |
wc -l |
입력의 줄 수 반환. 예: cat <filename> | wc -l. 단어 수를 세려면 wc만 사용 |
sort |
파일의 줄을 알파벳 순서로 정렬 |
uniq |
입력에서 중복된 줄 제거. 예: cat <filename> | uniq 또는 중복 파일만 보려면 uniq -d |
mv |
파일 이동 또는 이름 변경. 예: mv file1 file2는 이름을 변경하고, mv file1 ~은 홈 디렉토리로 이동 |
cp |
파일 복사. 예: cp file1 file2는 복사본을 만들고, cp file1 ~은 홈 디렉토리에 복사본 생성 |
rm <filename> |
파일 영구 삭제 |
rmdir <directory> |
비어 있는 디렉토리 영구 삭제 |
rm -rf <directory> |
⚠ 디렉토리 내의 모든 것을 영구 삭제 ⚠ |
grep <searchterm> |
특정 용어 검색. 예: cat hello_world.txt | grep world |
ls |
기본적으로 현재 디렉토리의 항목(파일 및 폴더) 나열 |
ls -a |
숨겨진 항목을 포함하여 현재 디렉토리의 모든 항목 나열 |
ls -l |
더 읽기 쉬운 형식으로 항목을 나열하고 권한 정보 표시 |
ls -S |
크기순으로 항목 나열 |
file <filename> |
<filename>의 파일 형식 정보 제공 |
find |
컴퓨터에서 특정 파일 찾기. 다른 명령어와 파이프로 연결 가능. 예: find *.md -size +5k -type f | xargs wc -l은 5KB보다 큰(.md로 끝나는 모든 파일의) 줄 수를 계산함 |
diff -u <filename1> <filename2> |
두 파일 간의 차이점에 대한 요약 표시 |
grep 명령어에 대한 더 자세한 내용, 제작: b0rk.
배시(bash)에서도 for 루프를 작성할 수 있습니다(기억하세요, 배시는 언어입니다). 일반적인 구조는 다음과 같습니다.
for i in LIST
do
OPERATION $i # $ 기호는 배시에서 변수를 나타냄
done이들은 한 줄로 압축될 수도 있습니다(가독성은 떨어지지만요):
for i in {1..5}; do echo $i; done더 흥미로운 예제로, 디렉토리에 있는 모든 CSV 파일의 텍스트 줄 수, 단어 수, 문자 수를 구하는 방법입니다:
for i in $(ls *.csv)
do
wc $i
done위의 예제를 더 멋지게 발전시켜서 그 개수들을 새로운 텍스트 파일에 담을 수도 있습니다:
touch counts_of_csvs.txt
for i in $(ls *.csv)
do
wc $i >> counts_of_csvs.txt
done위의 예제들에서 몇 가지 새로운 기능이 나타났습니다.
*는 와일드카드 문자로, “.csv”로 끝나는 모든 것을 찾으라고 배시에게 지시합니다. 이것이 유일한 특수 사례는 아닙니다. ?도 비슷한 목적으로 사용되지만, 임의의 개수가 아닌 딱 하나의 문자를 대신합니다. 만약 file1.csv, file2.csv 등 9번까지 있는 폴더가 있다면, file?.csv를 사용하여 모두 참조할 수 있지만 file10.csv는 선택되지 않을 것입니다.
이미 보았던 또 다른 특수 문자는 중괄호 {}입니다. 일련의 명령어들에서 공통된 부분 문자열이 있을 때마다 중괄호를 사용하면 명령줄이 그 안의 내용을 자동으로 확장하도록 할 수 있습니다. 위의 예제에서 이는 1부터 5까지 사용되었습니다. 하지만 파일 이름 등에서도 사용될 수 있습니다:
cp /path/to/project/{foo,bar,baz}.csv /newpath이는 foo.csv, bar.csv, baz.csv라는 이름의 csv 파일들을 /newpath 디렉토리로 복사합니다. 이와 유사하게,
touch {a..c}{.csv,.txt}는 a.csv, a.txt, b.csv, b.txt, c.csv, c.txt 파일을 생성합니다.
스크립팅 (Scripting)
반복될 작업의 경우, 매번 기억해내며 실행하는 것보다 터미널 명령어를 스크립트에 담아두는 것이 훨씬 재현 가능하고 신뢰할 수 있으며, 훨씬 쉽습니다! 명령줄은 자체적인 언어를 가지고 있기 때문에, 명령어를 실행하는 스크립트를 만들 수 있습니다. 배시(bash)와 zsh 사이에는 약간의 차이가 있지만 가이드는 일반적으로 유지하겠습니다.
hello_world.sh라는 스크립트를 만드세요. 내부에 다음과 같이 작성합니다:
#!/bin/bash
echo "Hello World!"첫 번째 줄은 쉬뱅(shebang)이라고 불리며, 아래의 명령어들을 어떤 프로그램으로 실행할지 알려줍니다(sh는 모든 배시 호환 쉘을 의미합니다). # 문자는 주석을 나타내기도 합니다. 두 번째 부분은 화면에 문자열을 출력할 것입니다. 이제 배시나 zsh 중 사용 중인 것에 따라 다음을 실행하세요.
bash hello_world.sh
# 또는
zsh hello_world.sh더 복잡한 예제를 보겠습니다:
#!/bin/bash
echo "Starting program at $(date)"
echo "Running program $0 with $# arguments결과물은 다음과 같습니다.
Starting program at Thu 25 Mar 2021 21:23:22 GMT
Running program hello_world.sh with 0 arguments"$(command)"를 사용하면 명령어의 출력이 텍스트 문자열에 삽입되는 것을 확인하세요. 배시와 zsh 스크립트에서 변수를 할당하려면 foo=bar 구문(공백 없음)을 사용하고, $foo로 변수의 값에 접근하세요.
문자열은 '와 " 구분자로 정의될 수 있지만, 두 방식이 동일하지는 않습니다. '로 구분된 문자열은 리터럴 문자열로 변수 값을 치환하지 않지만, "로 구분된 문자열은 치환합니다.
배시와 zsh는 그 용도 때문에 다른 언어와 비교했을 때 몇 가지 특이한 기능을 가지고 있습니다. 그중 하나가 미리 정의된 특수 변수들인데, 위의 예제에서도 하나를 보았습니다. 주요 목록은 다음과 같습니다:
$0- 스크립트의 이름$1~$9- 스크립트의 인수 (숫자 순서대로)$@- 모든 인수들$#- 인수의 개수!!- 인수를 포함한 바로 직전의 전체 명령어
더 많은 특수 변수들은 여기에서 찾을 수 있습니다.
유용한 명령줄 도구들
pandoc은 정말 훌륭합니다: 텍스트가 포함된 파일을 한 형식에서 다른 형식으로 변환해야 한다면, 이것은 진정한 맥가이버 칼과 같습니다. 여기서 변환 가능한 방대한 문서 목록을 다 나열할 수는 없지만, 중요한 점은 마크다운, \(\LaTeX\), 마이크로소프트 워드의 docx, 오픈오피스의 ODT, HTML, 그리고 주피터 노트북 사이를 서로 자유롭게 번역할 수 있다는 것입니다.
또한 이러한 형식들(및 그 이상)로부터 한 방향으로 PDF, 마이크로소프트 파워포인트, \(\LaTeX\) Beamer를 생성할 수도 있습니다.
pandoc을 사용하려면 웹사이트의 지침에 따라 설치한 후 다음과 같이 호출하세요:
pandoc mydoc.tex -o mydoc.docx이는 .tex 문서가 입력이고, -o를 통한 출력이 마이크로소프트 워드 docx 파일인 예제입니다.
pandoc으로 상당히 정교한 작업도 할 수 있습니다. 예를 들어 책 한 권 분량의 latex을 워드 스타일, biblatex을 통한 참고문헌, 방정식, 그림이 모두 포함된 워드 문서로 번역할 수 있습니다. 워드 자체의 불편함을 완전히 해결할 수는 없어도 pandoc이 큰 도움을 주는 것은 확실합니다.
eza는 ls 명령어를 업그레이드한 것입니다. 더 많은 기능과 더 나은 기본 설정을 갖춘 개선된 파일 나열 도구로 설계되었습니다. 색상을 사용하여 파일 형식과 메타데이터를 구분합니다. 웹사이트의 지침에 따라 운영 체제에 설치하세요. ls를 eza로 대체하려면 터미널 별칭(alias)을 사용할 수 있습니다. 좋은 가이드가 여기에 있습니다.
nano는 터미널 내부에서 실행되는 내장 텍스트 에디터입니다. 클라우드에서 작업할 때 매우 유용할 수 있습니다(단, VS Code와 같은 GUI 기반 에디터처럼 풍부한 기능은 없습니다). nano를 사용하여 파일을 열려면 nano file.txt 명령어를 사용합니다. 나노는 로드될 때 탐색 방법에 대한 안내를 표시하지만 종료가 가장 어렵습니다: 작업이 끝나면 Ctrl+X를 누르고, 저장하려면 y를 누른 뒤, enter를 눌러 나갑니다.
wget은 인터넷에서 파일을 다운로드하기 위한 명령줄 유틸리티입니다. 사용법은 매우 간단하며 구문은 wget [options] [url]입니다. 예를 들어, 이 책에서 사용된 starwars csv 파일을 다운로드하려면 명령어는 다음과 같습니다.
wget https://github.com/aeturrell/coding-for-economists/blob/main/data/starwars.csvhtop은 컴퓨터에서 현재 실행 중인 프로세스들(개별 프로세서별로)과 메모리 사용량을 언제든 확인할 수 있게 해주는 도구입니다. 맥에서는 홈브루(homebrew)를 사용 중이라면 brew install htop으로 설치할 수 있습니다. 그렇지 않다면 웹사이트에서 다운로드하여 소스에서 컴파일할 수 있습니다. 사용하려면 명령줄에 htop을 입력하기만 하면 됩니다.
ncdu는 디스크 사용량 분석기입니다. 폴더가 차지하는 공간이 얼마인지 터미널을 통해 대화형으로 보고합니다. 엔터 키를 사용하여 폴더 내부로 들어가 하위 폴더를 탐색할 수도 있습니다. 그래픽 사용자 인터페이스(GUI)를 볼 수 없는 원격 컴퓨터를 사용할 때 특히 유용합니다.
ffmpeg는 “인간과 기계가 만든 거의 모든 것을 디코딩, 인코딩, 트랜스코딩, 믹싱, 디믹싱, 스트리밍, 필터링 및 재생”하는 것을 목표로 하는 명령줄 도구입니다. 모든 용도에 대해서는 문서를 참고하세요.
yank는 표준 입력(터미널에서 보는 내용)을 읽어 필드를 선택하고 클립보드에 복사할 수 있는 선택 인터페이스를 표시합니다. 전형적인 사용 사례는 ls 명령어로 찾은 파일 이름을 복사해서 붙여넣는 것입니다. 예를 들어 디렉토리에서 ls -lah | yank를 실행하면 권한, 크기, 사용자, 수정 날짜 및 파일 이름 목록이 나타납니다. 키보드로 원하는 파일 이름으로 이동하여 엔터를 누르면 해당 파일 이름이 클립보드에 저장되어 다음 터미널 명령어에 바로 붙여넣을 수 있습니다. 여기에 좋은 데모가 있습니다.
명령줄에 대한 더 자세한 내용은 The Art of the Command Line을 참고하세요. 다른 명령어 중에는 patch, sed, awk 등을 확인해 보시면 좋습니다.