AI의 답을 직접 실행
에게 "이 폴더의 파일들을 이렇게 정리해줘"라고 부탁하면 AI는 거의 항상 로 답을 줍니다. 그래서 을 읽을 줄 알아야 AI의 답이 안전한지 스스로 검증할 수 있습니다.
를 배우면 을 먼저 떠올리지만, AI 도구를 설치하고 실행하는 데는 와 이 든든한 기본기가 됩니다.
쉘은 AI 을 직접 만드는 주력 언어는 아니지만, 파이썬보다 오래전부터 파일 관리와 작업 자동화에 쓰여 온 도구입니다.
깊이 공부할 필요 없이, 자주 쓰는 명령어 몇 가지만 익혀 보세요. 쉽게 시작해 평생 활용할 기본기가 됩니다.
은 실행·파일 관리·개발 자동화에 유용해요. 는 ·앱·노트북·로도 사용할 수 있어요. 은 유용한 인터페이스 중 하나이며 모든 AI 사용자의 필수 조건은 아니에요.
기초 부터 ·개발 도구, ·· 같은 다른 언어 실행, 까지 짧게 배우고 바로 실행해 보세요.
을 열고, 파일을 다루고, 글을 찾아 세고, 명령을 이어 붙입니다. 이 네 단원만 끝내도 터미널을 혼자 쓸 수 있어요.
값을 담고(), 판단하고 되풀이하고(조건·반복), 명령 묶음에 이름을 붙여() 나만의 자동화를 안전하게 만듭니다.
와 개발 도구를 설치하고, 에서 ···을 부려 실제 일을 합니다.
에게 "이 폴더의 파일들을 이렇게 정리해줘"라고 부탁하면 AI는 거의 항상 로 답을 줍니다. 그래서 을 읽을 줄 알아야 AI의 답이 안전한지 스스로 검증할 수 있습니다.
쉘은 40년 넘게 거의 바뀌지 않은, 가장 안정적이고 어디에나 있는 "컴퓨터의 공용어"입니다. 한 번 배워 두면 macOS····AI 도구 어디서든 평생 써먹습니다. 인공지능 시대에 사람이 컴퓨터·AI와 대화하는 가장 기본이 되는 실전 언어가 바로 쉘입니다.
macOS의 기본 쉘은 이지만, 이 과정에서 배우는 와 문법(····// 등)은 zsh 에서도 거의 100% 그대로 동작합니다. 스크립트 첫 줄에 를 적으면 macOS 에서도 정확히 bash 로 실행되며, 인덱스 시작 번호 같은 극히 일부 고급 차이를 빼면 그대로 통합니다. 그러니 안심하고 bash 기준으로 배우세요.
20줄 남짓한 로, 에 실제로 페이지를 돌려주는 웹 를 띄울 수 있습니다. 가 결국 "텍스트 한 덩어리를 주고받는 약속"임을 보여 주는 예제입니다.
#!/bin/bash
PORT=8084
PIPE=simple-web-server-pipe
rm -f "$PIPE"
mkfifo "$PIPE"
response() {
read -r method path _
echo "[$(date)] $method $path" >&2
index=$(cat index.html)
printf 'HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nConnection: close\r\n\r\n%s' \
"$index"
}
while true; do
response < "$PIPE" | nc -l "$PORT" > "$PIPE"
done
mkfifo "$PIPE"
를 만듭니다. 가 받은 요청과 우리가 만든 응답이 이 통로로 오갑니다.
nc -l "$PORT"
nc(netcat) 로 8084 를 열고 브라우저 접속을 기다립니다. 서버를 한 줄로 대신합니다.
response()
요청 첫 줄(메서드·)을 읽어 로그를 남기고, index.html 을 HTTP 200 응답으로 만들어 돌려줍니다.
while true; do … done
응답을 마치고 연결이 끊기면 가 다시 돌아 다음 손님을 받습니다. 덕분에 서버가 계속 살아 있습니다.
같은 폴더에 index.html 을 두고 bash server.sh 로 실행한 뒤, 브라우저에서 :8084 를 열어 보세요. 실서비스용은 아니지만 HTTP 의 원리를 이해하기에 좋습니다.
을 열고 를 입력하는 기본 규칙과, 지금 내가 컴퓨터의 어디에 있는지 파악하는 방법을 배웁니다.
쉽게 말하면 컴퓨터와 글자로 나누는 첫 대화입니다. 한 줄 말하면 한 줄 대답합니다.
파일과 폴더를 직접 만들고 복사·이동·삭제하며, 파일 내용을 들여다보는 실전 파일 관리를 익힙니다.
쉽게 말하면 파일 탐색기에서 마우스로 하던 만들기·복사·이동·삭제를 글자로 합니다.
파일과 출력에서 원하는 줄을 찾고(), 정렬·중복제거·개수 세기(··)를 하는 강력한 텍스트 도구를 배웁니다.
쉽게 말하면 아주 긴 글에 쓰는 형광펜·줄 세우기·개수 세기 도구입니다.
명령의 출력을 다른 명령의 입력으로 잇는 (|)와, 결과를 파일로 보내는 (>, >>)을 배웁니다.
쉽게 말하면 컨베이어 벨트처럼 명령의 결과를 다음 명령으로 넘기고, 끝에서 상자(파일)에 담습니다.
값을 에 담아 재사용하고, 명령 결과나 계산 결과를 문장 속에 끼워 넣는 ""을 배웁니다.
쉽게 말하면 이름표 붙인 상자에 값을 넣어 두고, 나중에 이름으로 꺼내 쓰는 것입니다.
상황에 따라 다르게 동작하는 (if)과, 같은 일을 여러 번 반복하는 (for·while)을 배웁니다.
쉽게 말하면 '비가 오면 우산을 챙긴다', '계단을 열 번 오른다'처럼 판단과 되풀이를 시킵니다.
자주 쓰는 명령 묶음을 로 만들고, 를 넘겨 호출하는 방법을 배웁니다. 파일과 (#!/bin/bash)의 역할도 이해합니다.
쉽게 말하면 자주 하는 일을 레시피 카드로 적어 두고 이름만 부르면 해 주게 만듭니다.
지금까지 배운 조각들을 모아, 를 검증하고 성공·실패를 확인하며 실제 작업을 자동화하는 완성형 의 원리를 배웁니다.
쉽게 말하면 도미노처럼 앞 일이 성공해야 다음 일이 넘어가게 만듭니다.
초보자가 가장 많이 당하는 ·· 함정을 정리하고, 오류에 강한 "방어적 " 작성법을 익힙니다.
쉽게 말하면 안전벨트처럼 따옴표와 안전 이 사고를 미리 막아 줍니다.
현대 웹· 도구의 기반인 를 에서 다루는 법을 배웁니다. 버전 확인, 실행, 관리, 일회 실행까지 익힙니다.
쉽게 말하면 코드용 앱 스토어처럼 npm 이 도구를 받아 오고, 가 를 실행합니다.
와 도구를 에 설치하는 짧은 안내입니다. Node/ 이 준비되면 대부분 한 줄 명령으로 시작할 수 있습니다.
쉽게 말하면 새 작업실에 공구를 들여놓고 하나씩 잘 되는지 확인하는 일입니다.
은 모든 것을 혼자 하지 않습니다. ·· 같은 다른 언어를 불러 쓰는 지휘자입니다. 한 줄로 넘기는 -c, 여러 줄을 통째로 넘기는 , 그리고 이 가장 많이 쓰는 sed·awk 를 배웁니다.
쉽게 말하면 통역사처럼 쉘이 파이썬·awk·sed 에게 일을 맡기고 결과를 받아 옵니다.
(정규식, regex)은 찾고 싶은 글자의 모양을 기호로 적는 작은 언어입니다. 날짜·이메일·처럼 값은 달라도 모양이 같은 글을 으로 찾고, 로 바꾸고, 와 에서 검사합니다. macOS··윈도우에서 처음부터 쓸 수 있는 명령도 함께 익힙니다.
쉽게 말하면 '숫자 세 개-숫자 네 개' 같은 모양 도장으로 맞는 글을 모두 찾습니다.
명령어 [] 형태의 기본 구조로 명령을 입력할 수 있다
를 확인하고 폴더 사이를 이동할 수 있다
로 화면에 원하는 글자를 출력할 수 있다
man 과 --help 로 모르는 명령어를 스스로 찾아볼 수 있다
따라 해 보기 예제를 누르면 명령이 실습 터미널 입력줄에 들어가요. Enter 를 눌러야 실행되고, 그 전에 고쳐 써도 돼요.
은 컴퓨터에게 글자로 명령을 내리는 창입니다. 명령을 기다리는 표시(보통 $ 또는 %)를 라고 부르며, 여기에 를 한 줄씩 적고 Enter 를 누르면 실행됩니다. 창 안에서 명령을 알아듣고 실행하는 이 (여기서는 )이고, 이렇게 글자로 컴퓨터를 다루는 방식을 (명령줄 인터페이스)라고 합니다.
대부분의 는 "무엇을 할지(명령어) + 어떻게 할지() + " 세 부분으로 되어 있습니다. 예를 들어 -l notes.txt 는 "목록 보기(ls) + 자세히(-l) + notes.txt 파일"이라는 뜻입니다. 모르는 명령은 man 뒤에 그 이름을 쓰거나 명령 뒤에 --help 를 붙이면 설명서를 볼 수 있습니다(실습 에서는 짧은 요약만 나옵니다).
에서는 항상 "지금 어느 폴더에 있는가"가 중요합니다. 로 를 확인하고, 로 폴더를 옮겨 다니며, 로 그 안에 무엇이 있는지 봅니다. ~ 는 내 를, .. 는 를 뜻합니다.
이 화면에서는 아무것도 설치하지 않고 실습 에서 바로 연습합니다. 내 컴퓨터에서는 Mac 이면 터미널 앱(Spotlight 에서 '터미널' 검색)을, Windows 면 시작 메뉴에서 을 엽니다. 이 과정과 같은 명령을 Windows 에서 쓰려면 을 설치하고 Ubuntu 를 엽니다. 대부분의 에서는 Ctrl+Alt+T 를 누릅니다.
폴더와 빈 파일을 로 만들 수 있다
파일을 복사·이동·이름 변경·삭제할 수 있다
파일 내용을 ·· 로 확인할 수 있다
삭제 명령의 위험성을 이해하고 안전하게 사용할 수 있다
따라 해 보기 예제를 누르면 명령이 실습 입력줄에 들어가요. Enter 를 눌러야 실행되고, 그 전에 고쳐 써도 돼요.
은 새 폴더를, 는 빈 파일을 만듭니다. mkdir -p a/b/c 처럼 -p 를 붙이면 까지 한 번에 만들어 줘서 편리합니다. 대부분의 명령처럼 성공하면 아무것도 출력하지 않으니, 로 결과를 확인하세요.
는 원본을 남기고 복사본을 만들고, 는 원본을 다른 곳으로 옮깁니다. 재미있게도 mv 옛이름 새이름 은 "이름 바꾸기"로도 쓰입니다.
은 파일 전체를 보여 주고, 는 앞부분 몇 줄, 은 끝부분 몇 줄만 보여 줍니다. 은 파일을 삭제하는데 휴지통을 거치지 않고 즉시 영구 삭제되므로 조심해야 합니다.
grep 으로 특정 단어가 든 줄을 찾을 수 있다
grep 의 -i·-n 을 활용할 수 있다
sort 로 줄을 정렬할 수 있다
wc 로 줄 수·단어 수를 셀 수 있다
따라 해 보기 예제를 누르면 명령이 실습 입력줄에 들어가요. Enter 를 눌러야 실행되고, 그 전에 고쳐 써도 돼요.
단어 파일 은 그 단어가 들어간 줄만 골라 보여 줍니다. -i 는 무시, -n 은 줄 번호 표시, -r 은 폴더 전체 검색으로, 로그나 에서 원하는 부분을 순식간에 찾습니다.
는 줄을 정렬하고, 는 (정렬된) 중복 줄을 하나로 합치며, -l 은 줄 수를 셉니다. 이들을 조합하면 간단한 통계를 낼 수 있습니다.
파이프 | 로 여러 명령을 연결할 수 있다
> 로 결과를 파일에 저장할 수 있다
>> 로 파일 끝에 이어 붙일 수 있다
의 흐름을 바꾸는 개념을 이해한다
따라 해 보기 예제를 누르면 명령이 실습 입력줄에 들어가요. Enter 를 눌러야 실행되고, 그 전에 고쳐 써도 돼요.
명령A | 명령B 는 A 의 출력을 B 의 입력으로 곧장 넘깁니다. | txt 처럼 이으면 여러 도구를 조립해 강력한 한 줄을 만들 수 있어, 의 진정한 힘이 여기서 나옵니다.
> 파일 은 결과를 파일에 저장(), >> 파일 은 뒤에 , < 파일 은 파일 내용을 명령의 입력으로 넣습니다. 오류만 따로 저장하려면 2> 오류.txt 를 씁니다.
중간에 를 끼우면, 흘러가는 내용을 화면(또는 다음 명령)으로 그대로 보내면서 동시에 파일로도 저장합니다. 이름은 배관의 T자 이음새(tee)에서 왔어요. > 는 출력을 파일로 "돌려버려" 화면에서 사라지지만, 명령 | tee 파일 은 화면에도 보여 주면서 저장하는 점이 다릅니다. 지우지 않고 tee -a 를 씁니다. 로그를 남기면서 결과도 눈으로 확인할 때 특히 유용합니다.
변수를 만들고 값을 꺼내 쓸 수 있다
변수를 로 안전하게 감쌀 수 있다
$(( )) 로 간단한 계산을 할 수 있다
$( ) 로 명령 결과를 값처럼 가져올 수 있다
따라 해 보기 예제를 누르면 명령이 실습 입력줄에 들어가요. Enter 를 눌러야 실행되고, 그 전에 고쳐 써도 돼요.
이름=값 형태로 를 만들고, 꺼낼 때는 앞에 $ 를 붙여 $이름 으로 씁니다. 중요한 규칙은 = 양옆에 공백을 넣지 않는 것입니다 (name=리엔 은 O, name = 리엔 은 X).
를 쓸 때는 "$name" 처럼 로 감싸는 것이 안전합니다. 값에 공백이 있어도 하나의 값으로 지켜지며, 이는 9단원에서 배울 "함정 예방"의 핵심 습관입니다.
숫자 계산은 $(( )) 안에서 합니다. $(( 3 + 4 )) 는 7 을 돌려줍니다. $() 를 쓰면 그 명령어의 실행 결과를 값처럼 가져와 에 담거나 문장에 끼울 수 있습니다. 예: 오늘=$(date).
if / elif / else 로 조건에 따라 분기할 수 있다
[[ ]] 로 ·숫자·파일을 비교할 수 있다
for 로 목록을 하나씩 반복 처리할 수 있다
숫자 비교와 문자열 비교의 차이를 안다
따라 해 보기 예제를 누르면 명령이 실습 입력줄에 들어가요. Enter 를 눌러야 실행되고, 그 전에 고쳐 써도 돼요.
if 조건; then ... fi 구조로, 조건이 참일 때만 안쪽 명령이 실행됩니다. elif(그밖에 이 경우)와 else(나머지 전부)를 덧붙일 수 있고, 반드시 fi 로 닫습니다.
조건 검사에는 를 권장합니다. 은 ==·!=, 숫자는 -eq(같다)·-gt(크다)·-lt(작다)·-ge(크거나 같다)·-le(작거나 같다), 파일 존재는 -f(파일)·-d(폴더)로 확인합니다.
for in 목록; do ... done 은 목록의 각 항목을 하나씩 변수에 넣어 반복합니다. {1..5} 처럼 범위를 쓰거나, 파일 목록을 돌 수도 있습니다.
1부터 20까지처럼 "정해진 횟수"를 반복하려면 로 숫자를 만들어 for 에 넘깁니다. for i in $(seq 1 20); do ... done 처럼 쓰며, $(seq 1 20) 이 1 2 3 … 20 을 대신 만들어 줍니다. 이때 in 을 빠뜨리고 for i $(seq 1 20) 처럼 쓰면 오류가 나니, "for in 목록" 순서를 꼭 지키세요. 같은 반복을 for i in {1..20} 처럼 브레이스로도 쓸 수 있어요.
함수를 정의하고 호출할 수 있다
함수에 인자($1)를 넘겨 활용할 수 있다
셔뱅(#!/bin/bash)의 역할을 설명할 수 있다
( +x)의 개념을 이해한다
따라 해 보기 예제를 누르면 명령이 실습 입력줄에 들어가요. Enter 를 눌러야 실행되고, 그 전에 고쳐 써도 돼요.
이름() { 명령들; } 형태로 를 만들면, 자주 쓰는 명령 묶음을 이름 하나로 부를 수 있습니다. 함수 안에서는 $1, $2 로 넘어온 값을 받습니다.
여러 줄을 파일(예: hello.sh)에 저장해 두면 언제든 재실행할 수 있습니다. 파일 첫 줄의 ("셔뱅")는 "이 파일을 로 실행하라"는 표시이며, macOS 의 zsh 환경에서도 이 줄 덕분에 정확히 bash 로 실행됩니다.
만든 는 +x hello.sh 로 을 준 뒤 ./hello.sh 로 실행합니다. 스크립트나 에 넘긴 값은 $1(첫째), $2(둘째), $@(전부), $#(개수)로 받습니다.
명령의 성공·실패를 ($?)로 확인할 수 있다
로 성공·실패에 따라 다음 명령을 이을 수 있다
여러 파일을 for 반복으로 처리할 수 있다
으로 정해진 시각에 자동 실행하는 개념을 안다
따라 해 보기 예제를 누르면 명령이 실습 입력줄에 들어가요. Enter 를 눌러야 실행되고, 그 전에 고쳐 써도 돼요.
모든 명령은 끝날 때 성공(0)·실패(0이 아닌 값)를 나타내는 를 남깁니다. 바로 앞 명령의 결과는 $? 로 확인하며, 명령A 명령B 는 A 가 성공했을 때만 B 를 실행합니다.
파일 여러 개에 같은 작업을 하려면 for 반복과 파일 조작을 결합합니다. 예를 들어 폴더의 모든 사진을 백업 폴더로 날짜별로 복사하는 일을 몇 줄로 자동화할 수 있습니다.
-e 로 편집하는 cron 은 "매일 새벽 3시" 같은 정해진 시각에 를 자동 실행합니다. 분 시 일 월 요일 명령 으로 시각을 지정합니다. 예: 0 3 * * * 는 매일 새벽 3시.
큰따옴표·작은따옴표·따옴표 없음의 차이를 설명할 수 있다
단어 분리와 글로빙이 왜 위험한지 이해한다
set -euo pipefail 로 오류에 강한 스크립트를 만들 수 있다
는 언제나 큰따옴표로 감싸는 습관을 갖는다
따라 해 보기 예제를 누르면 명령이 실습 입력줄에 들어가요. Enter 를 눌러야 실행되고, 그 전에 고쳐 써도 돼요.
"$var"()는 는 풀되 공백은 지키고, '$var'(작은따옴표)는 안의 모든 것을 글자 그대로 두며, 따옴표 없는 $var 는 공백에서 쪼개지고 * 같은 글자가 파일명으로 바뀝니다. 의심스러우면 큰따옴표로 감싸는 것이 기본 원칙입니다.
없는 는 공백을 기준으로 여러 조각으로 나뉘고(), *·? 가 실제 파일명으로 바뀝니다(). 이 때문에 "공백 있는 파일.txt" 하나가 두 개 로 오해되는 사고가 납니다.
위쪽에 set -euo pipefail 을 넣으면 오류가 나면 즉시 멈추고(-e), 정의 안 된 를 쓰면 경고하고(-u), 중간 실패도 잡아냅니다(pipefail). 도구로 미리 검사하면 대부분의 함정을 걸러낼 수 있습니다.
node -v 로 Node.js 설치 여부와 버전을 확인할 수 있다
node app.js 로 자바스크립트 파일을 실행할 수 있다
npm 으로 패키지를 설치하고 스크립트를 실행할 수 있다
npx 로 없이 도구를 한 번 실행할 수 있다
따라 해 보기 예제를 누르면 명령이 실습 터미널 입력줄에 들어가요. Enter 를 눌러야 실행되고, 그 전에 고쳐 써도 돼요.
는 밖(·)에서 를 실행하는 입니다. 웹 프론트(SvelteKit 등), 도구, , 많은 가 Node 위에서 동작합니다. 을 배운 다음으로 익혀 두면 개발 도구 설치·실행이 훨씬 수월해집니다.
-v(또는 node --version)로 버전을 확인합니다. node app.js 는 파일을 실행하고, node -e "console.log(1+1)" 은 한 줄 를 바로 실행합니다. 파일이 없거나 문법 오류면 에러 메시지가 나옵니다.
(Node Manager)은 를 설치·관리하는 도구입니다. 프로젝트 루트의 package.json 에 이름·버전··dependencies 가 적혀 있습니다. npm install 로 의존성을 받고, npm run start 처럼 scripts 항목을 실행합니다. 는 패키지를 하지 않고 한 번만 실행할 때 씁니다.
가 개발 도구 설치의 전제임을 설명할 수 있다
Claude Code · Codex · Grok · 의 대표 설치 명령을 안다
(-g)와 일회 실행()의 차이를 구분할 수 있다
설치 후 버전 확인 습관을 갖는다
따라 해 보기 예제를 누르면 명령이 실습 터미널 입력줄에 들어가요. Enter 를 눌러야 실행되고, 그 전에 고쳐 써도 돼요.
현대 개발은 만으로 끝나지 않습니다. (Grok Build, OpenAI Codex, Claude Code), (Firebase tools), 관리자(pnpm 등)가 에서 동작합니다. 10단원에서 배운 · 이 그 출발점입니다.
공식 설치 방법은 바뀔 수 있으니 항상 공식 문서를 우선하세요. 일반적인 출발점은 다음과 같습니다. Claude : -fsSL ://claude.ai/install.sh | (또는 install -g @anthropic-/claude-code). OpenAI Codex: curl -fsSL https://chatgpt.com/codex/install.sh | sh (또는 npm install -g @openai/codex). Grok Build: 공식 안내의 설치 또는 npm install -g @xai-official/grok. : npm install -g firebase-tools. 설치 후 claude --version, codex --version, firebase --version 처럼 버전을 확인합니다.
인터넷에서 받은 ( | )는 가능하면 내용을 먼저 읽고, 신뢰할 수 있는 공식 출처만 사용하세요. 는 권한 오류가 나면 를 쓰기보다 환경을 점검하세요. 팀· 에서는 에 devDependency 로 고정해 버전을 맞추는 편이 안전합니다.
-c 와 -e 로 다른 언어를 한 줄 실행할 수 있다
을 파일로 저장해 python3 파일.py 로 실행할 수 있다
히어독(<<PY)으로 여러 줄짜리 프로그램을 명령에 넘길 수 있다
sed 로 파일의 텍스트를 규칙에 따라 일괄 수정할 수 있다
awk 로 표 형태 데이터에서 을 뽑고 집계할 수 있다
인공지능이 준 를 실행하기 전에 안전하게 확인할 수 있다
따라 해 보기 예제를 누르면 명령이 실습 입력줄에 들어가요. Enter 를 눌러야 실행되고, 그 전에 고쳐 써도 돼요.
하나로 모든 계산을 하려 들면 금방 벽에 부딪힙니다. 대신 쉘은 "누구를 언제 부를지" 정하는 지휘자 역할을 합니다. 수학·데이터는 에게, 표 계산은 에게, 텍스트 일괄 수정은 에게 시키고, 쉘은 그 결과를 이어 붙입니다. 그래서 쉘을 알면 배운 적 없는 언어도 "불러서 쓸" 수 있습니다.
대부분의 언어는 "를 로 받아 바로 실행하는" 을 가지고 있습니다. 은 -c "코드", 는 -e "코드", 펄은 -e, 루비는 ruby -e 입니다. 계산기 대신 python3 -c "print(2**10)" 을 치는 습관만 들여도 이 훨씬 강력해집니다.
이 한 번 쓰고 버릴 것이 아니라면 파일로 저장합니다. hello.py 에 를 적어 두고 hello.py 라고 치면 그대로 실행됩니다. 7단원에서 배운 을 파일 첫 줄에 #!/usr/bin/env python3 로 적고 +x hello.py 로 을 주면, python3 를 앞에 붙이지 않고 ./hello.py 만으로도 돌아갑니다. 실행이 끝난 뒤 를 쳐 보면 성공(0)인지 실패(1)인지 알 수 있어, 8단원에서 배운 대로 로 다음 명령을 이을 수 있습니다.
이 여러 줄이면 -c 로는 불편합니다. 이때 쓰는 것이 입니다. - <<'PY' 라고 쓰면, 그 다음 줄부터 PY 라고 적은 줄 전까지가 통째로 에게 으로 넘어갑니다. 가운데의 - 는 "파일 대신 표준입력에서 를 읽어라"는 뜻입니다. 코딩 가 파일을 고칠 때 자주 쓰는 형태가 바로 이것입니다.
를 로 감싸면(<<'PY') 본문이 글자 그대로 넘어갑니다. 감싸지 않으면(<<PY) 본문 안의 $와 $(명령) 을 이 먼저 바꿔치기합니다. 에는 $ 가 거의 없지만, 이나 에 $ 가 있으면 조용히 망가지므로 코드를 넘길 때는 따옴표로 감싸는 <<'PY' 가 기본입니다.
's/찾을것/바꿀것/' 은 각 줄에서 처음 만난 하나를, 끝에 g 를 붙이면(s/…/…/g) 그 줄의 모든 곳을 바꿉니다. 앞에 줄 번호나 // 을 붙여 대상 줄을 고르고(2s/…/…/, /error/s/…/…/), -n 과 p 를 함께 쓰면 고른 줄만 출력합니다. 는 / 가 아니어도 되어서, 를 바꿀 때는 s|/old/path|/new/path| 처럼 쓰면 훨씬 읽기 편합니다. 파일 자체를 고칠 때는 sed -i.bak 's/찾을것/바꿀것/' 파일 처럼 원본을 파일.bak 으로 남기는 형태가 안전합니다(macOS 와 의 차이는 아래 '주의'를 보세요).
는 가 아니라 그 자체로 언어입니다. 줄을 공백으로 쪼개 $1·$2·$3 으로 부르고, NF 는 , NR 은 줄 번호입니다. 기본 형태는 awk '패턴 { 할 일 }' 이며, 패턴을 생략하면 모든 줄, 할 일을 생략하면 줄 전체 출력입니다. 맨 앞에 BEGIN{}, 맨 뒤에 END{} 를 두면 시작·마무리 작업을 할 수 있어서, 합계·평균·항목별 집계를 한 줄로 끝냅니다.
으로 받아 표준출력으로 내보내도록 만들어진 프로그램끼리는 로 자유롭게 이을 수 있습니다. sales.txt | '{print $2}' | -n | -3 처럼 쓰면 "파일을 읽고 → 만 뽑고 → 숫자로 정렬하고 → 큰 값 셋만" 이 한 줄로 완성됩니다. awk· 는 이렇게 파이프로 잇고, 은 -c 나 으로 를 넘기는 것이 기본입니다. 이것이 이 지휘자라는 말의 진짜 의미입니다.
는 대개 이런 형태로 답을 줍니다. 그대로 붙여 넣기 전에 세 가지만 확인하세요. ① 어떤 파일을 고치는지 를 눈으로 읽는다. ② ·> 로 부분이 있는지 본다. ③ 중요한 파일이면 원본 원본.bak 으로 백업을 먼저 만든다. 을 읽을 줄 안다는 것은, AI 의 답을 검증할 수 있다는 뜻입니다.
. * + ? [ ] ^ $ 같은 기본 기호로 글자의 모양을 적을 수 있다
grep -E 로 패턴에 맞는 줄을 찾고, -o 로 맞는 부분만 뽑을 수 있다
sed -E 와 으로 글의 순서를 바꿔 고칠 수 있다
과 의 차이, \d 가 grep -E 에서 숫자가 아닌 까닭을 설명할 수 있다
쉘 스크립트의 [[ 값 =~ 패턴 ]] 과 파이썬의 re 모듈로 값을 검사할 수 있다
macOS·리눅스·윈도우에서 처음부터 쓸 수 있는 정규식 명령을 고를 수 있다
따라 해 보기 예제를 누르면 명령이 실습 입력줄에 들어가요. Enter 를 눌러야 실행되고, 그 전에 고쳐 써도 돼요.
글에서 전화번호를 모두 찾고 싶다고 해 봅시다. 010-1234-5678 을 그대로 찾으면 그 번호 하나만 나옵니다. 하지만 전화번호에는 "숫자 3개, 빼기, 숫자 4개, 빼기, 숫자 4개"라는 모양이 있습니다. 은 이 모양을 [0-9]{3}-[0-9]{4}-[0-9]{4} 처럼 기호로 적게 해 줍니다. 한 번 익혀 두면 ···vim···PHP 어디서나 거의 같은 기호를 씁니다.
. 은 아무 글자 하나입니다(a.c 는 abc 와 a1c). [abc] 는 괄호 안 글자 중 하나, [^abc] 는 괄호 안 글자를 뺀 하나, [a-z]·[0-9] 는 범위 안의 글자 하나입니다. 자주 쓰는 묶음은 줄여 씁니다 — \d 는 숫자, \w 는 낱말 글자(영문·숫자·_), \s 는 공백입니다. 대문자로 쓰면(\D \W \S) 반대가 됩니다. 도구에서는 [[:digit:]]·[[:space:]] 같은 이름도 씁니다.
* 는 바로 앞 글자가 0번 이상, + 는 1번 이상, ? 는 0번 또는 1번(colou?r 는 color 와 colour), {n} 은 정확히 n번, {n,m} 은 n번에서 m번입니다. 반복 기호는 바로 앞의 글자 하나(또는 하나)에만 붙습니다. 그리고 가능한 한 길게 잡으려 합니다() — ".*" 은 첫 부터 줄의 마지막 따옴표까지 통째로 잡으므로, 따옴표 하나 안만 원하면 "[^"]*" 처럼 씁니다.
^ 는 줄의 시작, $ 는 줄의 끝입니다. ^error 는 error 로 시작하는 줄, done$ 는 done 으로 끝나는 줄, ^$ 는 빈 줄입니다. \b 는 낱말의 경계라서 \bart\b 는 art 은 찾지만 party 는 찾지 않습니다. 이 기호들은 글자를 차지하지 않고 "자리"만 정합니다. 대괄호 맨 앞의 ^([^0-9])는 "빼고"라는 전혀 다른 뜻이니 헷갈리지 마세요.
red|blue 는 red 또는 blue 입니다. ( ) 는 여러 글자를 하나로 묶습니다 — (ab)+ 는 ab, abab, ababab 에 맞습니다. 묶음은 찾은 글을 따로 꺼내 쓰는 데도 씁니다. 에서는 \1 \2, 에서는 ${BASH_REMATCH[1]}, 에서는 m.group(1) 로 꺼냅니다. 그래서 2026-10-15 를 15.10.2026 으로 순서를 바꾸는 일이 한 줄로 끝납니다.
. * + ? ( ) [ ] { } ^ $ | \ 는 특별한 뜻이 있습니다. 이 글자 자체를 찾으려면 앞에 \ 를 붙입니다. 마침표는 \., 별표는 \*, 여는 괄호는 \( 입니다. 192.168.0.1 을 그대로 쓰면 . 이 "아무 글자"라서 192x168y0z1 도 맞습니다. 그리고 에서는 패턴을 꼭 로 감싸세요. 감싸지 않으면 쉘이 * ? $ { } 를 먼저 자기 식으로 바꿔 버립니다.
과 는 처음에 으로 읽습니다. BRE 에서는 + ? | ( ) { } 가 그냥 글자라서, 기능으로 쓰려면 \+ \| \( 처럼 \ 를 붙여야 합니다. grep -E · sed -E 를 붙이면 이 되어 기호를 그대로 씁니다 — 헷갈리면 늘 -E 를 붙이세요. \d 는 (PCRE) 기호라서 grep -E 에서는 숫자가 아니라 글자 d 가 됩니다. 도구에서는 [0-9] 를 쓰고, \d 를 꼭 쓰고 싶으면 grep -P()를 씁니다. ··PHP·(rg)은 처음부터 \d 를 압니다.
macOS 와 에는 ···find· 이 처음부터 있습니다. 다만 macOS 의 grep·sed 는 판이라 grep -P 가 없고, \s 대신 [[:space:]] 를 써야 하며, 파일을 고칠 때 sed -i 뒤에 '' 를 붙여야 합니다. 리눅스는 GNU 판이라 -P·\s·\+ 가 모두 됩니다. 윈도우의 에는 가, 에는 ·-match·-replace 가 있고, PowerShell 은 \d 를 그대로 압니다. 윈도우에서도 이나 를 깔면 grep·sed 를 그대로 씁니다. 아래 "운영체제별 기본 명령" 표에 예를 모았습니다.
에서는 [[ $값 =~ 패턴 ]] 으로 검사합니다. 맞으면 참이라 나 if 로 이을 수 있고, ( ) 로 묶은 부분은 ${BASH_REMATCH[1]} 에 들어갑니다. 패턴에 를 씌우면 글자 그대로 비교하므로, 패턴은 따옴표 없이 쓰거나 re='…' 처럼 에 담아 [[ $값 =~ $re ]] 로 씁니다. 은 import re 뒤에 re.search(찾기)·re.findall(모두 찾기)·re.sub(바꾸기)·re.fullmatch(전체 검사)를 쓰고, 패턴은 r"\d+" 처럼 앞에 r 을 붙인 원시 로 적습니다.
자주 쓰는 기호와 뜻, 예, 그 예에 맞는 글입니다. 예를 누르면 아래 테스트기에 들어가서 바로 확인할 수 있어요.
| 기호 | 뜻 | 예 | 맞는 글 |
|---|---|---|---|
. |
아무 글자 1개 | abc · a1c |
|
* |
앞 글자가 0번 이상 | ac · abbc |
|
+ |
앞 글자가 1번 이상 | abc · abbc |
|
? |
앞 글자가 0번 또는 1번 | color · colour |
|
{n,m} |
n번에서 m번 반복 | 12 · 2026 |
|
^ |
줄의 시작 | error: disk full |
|
$ |
줄의 끝 | all done |
|
[abc] |
괄호 안 글자 중 하나 | a · e |
|
[^abc] |
괄호 안 글자를 뺀 하나 | x · - |
|
[a-z] |
범위 안의 글자 하나 | Q · k |
|
| |
또는 | red · blue |
|
( ) |
여러 글자를 하나로 묶기 | ab · abab |
|
\ |
기호를 글자 그대로(이스케이프) | . |
| 기호 | 같은 표현 | 뜻 | 예 |
|---|---|---|---|
\d |
[0-9] |
숫자 하나 | 2026 |
\w |
[A-Za-z0-9_] |
낱말 글자 하나(영문·숫자·_) | user_1 |
\s |
[ \t\n] |
공백 하나(스페이스·탭·줄바꿈) | a b |
\D \W \S |
[^0-9] … |
각각의 반대 — 숫자·낱말 글자·공백이 아닌 것 | abc |
\b |
\< \> |
낱말의 경계 — \bart\b 는 art 만 찾고 party 는 뺀다 | art |
[[:space:]] |
\s |
POSIX 이름 — macOS 를 포함해 grep·sed 어디서나 되는 안전한 표현 | 42 |
과 는 처음에 으로 읽어서 + ? | ( ) { } 앞에 \ 가 있어야 기능이 됩니다. -E 를 붙이면 이 되어 기호를 그대로 씁니다.
| 기능 | 기본 문법(BRE) — grep · sed | 확장 문법(ERE) — grep -E · sed -E |
|---|---|---|
| 1번 이상 | \+ |
+ |
| 0번 또는 1번 | \? |
? |
| 또는 | a\|b |
a|b |
| 묶음 | \( \) |
( ) |
| n번에서 m번 반복 | \{n,m\} |
{n,m} |
기호를 그대로 쓰는 법
grep -E
sed -E
awk
[[ =~ ]]
grep -P
vim \v
\d \w \s 는 기호입니다. grep -E 에서 \d 는 숫자가 아니라 글자 d 라서 [0-9] 를 쓰세요. \d 가 필요하면 grep -P()·· 를 씁니다. macOS 의 grep·sed 에서는 \s 대신 [[:space:]] 가 안전합니다.
따로 설치하지 않아도 처음부터 쓸 수 있는 명령입니다. 탭을 눌러 내 운영체제를 고르세요.
grep -E
패턴에 맞는 줄 찾기( 판이라 -P 는 없다)
grep -E 'ERROR|WARN' app.log
sed -E
찾아 바꾸기 — 파일을 고칠 때는 -i 뒤에 '' 가 필요
sed -E -i '' 's/[[:space:]]+$//' notes.txt
awk
패턴에 맞는 줄에서 만 출력
awk '/ERROR/ {print $1, $3}' app.log
find -E
파일 이름을 으로 찾기(-E 가 )
find -E . -regex '.*\.(jpg|png)'
perl
\d 를 쓰는 치환 — 처음부터 설치되어 있다
perl -pe 's/(\d+)-(\d+)/$2-$1/g' a.txt
zsh [[ =~ ]]
macOS 의 기본 에서 값 검사하기
[[ $v =~ ^[0-9]+$ ]] && echo number
python3
re 모듈 — 처음 실행하면 설치 안내가 나올 수 있다
python3 -c "import re; print(re.findall(r'\d+', 'a1b22'))"
macOS 의 기본 쉘은 zsh 이고 · 는 BSD 판입니다. 와 똑같이 쓰고 싶으면 brew install grep gnu-sed 로 GNU 판(ggrep · gsed)을 깔 수 있어요.
grep -E · -P · -o
— -P 로 \d, -o 로 맞는 부분만
grep -Po '\d{4}-\d{2}-\d{2}' app.log
sed -E -i
파일을 바로 고치기 — GNU 는 \s · \+ 도 안다
sed -E -i 's/\s+$//' notes.txt
awk
열(필드)마다 조건 걸기
awk -F: '$1 ~ /^www/' /etc/passwd
find -regex
파일 를 정규식으로 찾기
find . -regextype posix-extended -regex '.*\.(php|js)'
bash [[ =~ ]]
값을 검사하고 을 로 꺼내기
[[ $s =~ ([0-9]+) ]] && echo "${BASH_REMATCH[1]}"
git grep
안에서만 빠르게 찾기
git grep -n -E 'TODO|FIXME'
python3
대부분의 배포판에 들어 있는
python3 -c "import re; print(re.sub(r'\s+', ' ', 'a b'))"
의 grep·sed 는 GNU 판이라, 이 단원의 실습 과 똑같이 동작합니다.
findstr
의 찾기 — 은 일부만(+ ? | 가 없다)
findstr /R /N "^ERROR" app.log
Select-String
의 — 패턴에 맞는 줄 찾기
Select-String -Path app.log -Pattern 'ERROR|WARN'
-match
맞으면 True, 묶음은 $Matches 에 들어간다
'2026-10-15' -match '^\d{4}-\d{2}-\d{2}$'
-replace
찾아 바꾸기 — \d \s 를 그대로 안다
(Get-Content a.txt) -replace '\s+$', '' | Set-Content a.txt
[regex]::Matches
맞는 곳을 모두 찾기
[regex]::Matches('a1b22', '\d+').Value
Where-Object
파일 이름을 정규식으로 고르기
Get-ChildItem | Where-Object Name -match '\.(jpg|png)$'
WSL · Git Bash
· 를 깔면 명령을 그대로
wsl grep -E 'ERROR|WARN' app.log
py
을 설치했다면 py 로 실행
py -c "import re; print(re.findall(r'\d+', 'a1b22'))"
PowerShell 은 .NET 정규식이라 \d \w \s 와 을 그대로 씁니다. 명령 프롬프트의 는 기능이 적어서 PowerShell 을 권합니다.
복사해서 바로 쓰는 패턴입니다. 누르면 테스트기에 들어가서 어디에 맞는지 바로 보여요.
패턴을 고치면 아래 글에서 맞는 부분이 바로 칠해집니다. 글도 마음대로 고쳐 보세요.
이 테스트기는 () 이라 \d 같은 기호가 됩니다. 에서 똑같이 하려면 -P 를 쓰거나, \d 를 [0-9] 로 바꿔 grep -E 를 쓰세요.
사용자에게 값을 물어보고 에 담습니다. 변수를 미리 선언할 필요가 없습니다.
echo "이름이 뭐예요?"# 질문을 화면에 출력read name# 입력을 받아 name 변수에 저장echo "안녕, $name!"# 받은 값을 사용명령 대신 $PWD 로도 를 알 수 있습니다. 괄호 ( )로 감싼 명령은 별도의 에서 돌아, 그 안에서 해도 원래 위치는 바뀌지 않습니다.
echo "나는 $PWD 에 있어요"# 로 현재 사용(cd /tmp; pwd)# 서브셸 안에서만 이동 → /tmp 출력pwd# 바깥은 원래 위치 그대로clear(또는 Ctrl-L)로 화면을 정리합니다. 모르는 명령은 세 가지 도움말로 찾습니다: 내장 명령은 help, 매뉴얼은 man, 상세 문서는 info.
clear# 화면 비우기 (Ctrl-L 과 같음)help for# 내장 명령(for 등)의 도움말man ls# 의 매뉴얼 페이지 (q 로 나감){ } 안에 값을 나열하거나 범위를 쓰면 여러 이름을 한 번에 생성합니다. 폴더 트리를 한 줄로 만들 때 특히 강력합니다.
mkdir -p project/{src,tests,docs}# 폴더 3개를 한 번에 생성touch file{1..5}.txt# file1.txt ~ file5.txt 다섯 개 생성cp config.yaml{,.bak}# config.yaml → config.yaml.bak 백업 트릭은 되돌릴 수 없습니다. -i(하나씩 확인)·-v(지운 것 표시)로 실수를 줄이고, trash- 를 쓰면 휴지통으로 보냅니다.
rm -i old.txt# 지우기 전에 정말 지울지 물어봄rm -v *.tmp# 무엇을 지웠는지 보여줌rm -r tempDir/# 폴더와 내용 전부 삭제(주의!)는 으로 정렬·형식을 바꿉니다. 자주 쓰는 세 가지를 익혀두면 편합니다.
ls -l# 한 줄에 하나씩, 자세히ls -t# 최근 수정순으로 정렬ls -R# 재귀적으로은 으로 훨씬 강력해집니다. 검색·줄 번호·제외·개수 세기 등을 조합합니다.
grep -r "TODO" ./src# -r: 폴더 전체를 재귀 검색grep -n "error" app.log# -n: 줄 번호와 함께grep -v "debug" app.log# -v: 그 단어가 없는 줄만(반대)grep -c "error" app.log# -c: 몇 줄인지 개수만는 텍스트를 흐르는 대로 편집합니다. 치환·삭제·범위 지정이 가능하고, -i 로 파일을 직접 고칠 수 있습니다(백업 권장).
sed 's/okay/great/g' file.txt# 모든 okay 를 great 로sed '/^#/d' file.txt# # 로 시작하는 줄 삭제sed -i.bak 's/old/new/g' file.txt# 파일 직접 수정 + .bak 백업sed -n '/error/p' log.txt# error 가 든 줄만 출력는 각 줄을 공백(또는 -F 로 지정한 문자)으로 쪼개 $1, $2 … 다룹니다. 합계·필터·통계에 강력합니다.
echo 'a b c' | awk '{print $2}'# 두 번째 열 → bawk -F',' '{print $3}' data.csv# 쉼표로 나눠 3번째 열awk -F',' '$2 > 25' people.csv# 2번째 열이 25 초과인 줄awk '{s+=$1} END{print s}' nums.txt# 1번째 열 합계작은 도구들을 로 이으면 강력한 데이터 처리가 됩니다. 는 앞 명령의 출력을 다음 명령의 로 넘깁니다.
cut -d ',' -f 1 file.csv# 쉼표 기준 첫 만sort file.txt | uniq -c# 정렬 후 중복 개수 세기find . -name "*.tmp" | xargs rm -f# 찾은 파일들을 에 넘겨 삭제find . -name "*.txt" -print0 | xargs -0 rm# 공백 있는 파일명도 안전(-0)<< EOF 는 여러 줄 텍스트를 명령의 입력으로 통째로 넘깁니다. <<< 는 짧은 한 줄 을 입력으로 넣는 가벼운 방법입니다.
cat << EOF# EOF 까지 여러 줄을 입력으로여러 줄
텍스트
EOF# 두 EOF 사이가 내용grep "바나나" <<< "사과 바나나 포도"# <<< 로 한 줄 입력출력()과 오류(stderr)는 다른 통로입니다. 2> 는 오류만, 2>&1 은 오류를 출력과 같은 곳으로, /dev/null 은 "버리는 곳"입니다.
command 2> error.log# 오류 메시지만 파일로command > out.log 2>&1# 출력과 오류를 함께 out.log 로command > /dev/null 2>&1# 출력·오류 모두 버리기(조용히)<(명령) 은 명령의 출력을 마치 파일인 것처럼 넘깁니다. 두 명령의 결과를 임시 파일 없이 바로 비교할 때 유용합니다.
diff <(ls dir1) <(ls dir2)# 두 폴더 목록을 바로 비교while read l; do echo "$l"; done < <(ls)# 안 가 밖에도 남음$(명령) 은 명령의 결과를 값처럼 문장에 끼웁니다. 백틱(`)보다 $( )를 권장합니다(중첩 가능).
echo "여기 파일 $(ls | wc -l)개"# 파일 개수를 문장에 끼움today=$(date +%Y-%m-%d)# 오늘 날짜를 에${ } 안에서 값을 꺼내는 동시에 잘라내거나 바꿀 수 있습니다. 값을 가공하는 가장 강력한 도구입니다.
echo "${var/Some/A}"# 첫 번째 Some 을 A 로 치환echo "${var//Some/A}"# // 는 모든 Some 을 A 로 치환echo "${var:0:7}"# 0번째부터 7글자만 (부분 )echo "${#var}"# 문자열 길이가 비어 있을 때 기본값을 주거나, 를 한 번에 바꿀 수 있습니다.
echo "${foo:-기본값}"# foo 가 비었으면 "기본값"을 대신 사용: "${NAME:=손님}"# NAME 이 없으면 "손님"으로 설정하고 유지echo "${var^^}"# 모두 대문자 ( 4+)echo "${var,,}"# 모두 소문자# 는 앞에서, % 는 뒤에서 잘라냅니다. 두 번 쓰면(##, %%) 가장 길게 잘라, 에서 파일명·폴더명만 뽑을 때 씁니다.
path="/usr/local/bin/run.sh"# 예시 경로echo "${path##*/}"# 맨 뒤 / 까지 제거 → run.sh ()echo "${path%/*}"# 맨 뒤 /이후 제거 → /usr/local/bin (dirname)echo "${path%.sh}"# .sh 만 제거괄호로 여러 값을 담고, [번호]로 하나씩, [@]로 전부 꺼냅니다. ${#array[@]} 로 개수를 셉니다.
array=(사과 바나나 포도)# 3개짜리 만들기echo "${array[0]}"# 첫 번째 → 사과 (번호는 0부터)echo "${array[@]}"# 전부 → 사과 바나나 포도echo "${#array[@]}"# 개수 → 3-A 로 만든 은 "이름 → 값" 짝으로 저장합니다(다른 언어의 딕셔너리/맵과 같음).
declare -A person# 연관 배열 선언person[name]="앨리스"# 이름표 name 에 값 저장echo "${person[name]}"# 꺼내기 → 앨리스for k in "${!person[@]}"; do echo "$k"; done# 모든 키 순회가 미리 채워 두는 들이 있습니다. 은 $(( )) 안에서 하며, 지수·나머지도 가능합니다. 소수 계산은 를 씁니다.
echo "$?"# 바로 앞 명령의 (0=성공)echo "$RANDOM"# 0~32767 사이 난수echo "$(( 2 ** 10 ))"# 지수 → 1024echo "scale=2; 10/3" | bc# 소수 계산 → 3.33는 시스템마다 동작이 조금씩 다릅니다. 는 어디서나 똑같이 동작하고, 자릿수·정렬·소수점을 정밀하게 다룹니다.
printf "안녕, %s!\n" "세계"# %s 자리에 값을 끼움 → 안녕, 세계!printf "%.2f\n" 3.14159# 소수 둘째 자리 → 3.14printf "%05d\n" 42# 5자리 0채움 → 00042하나의 값을 여러 패턴과 비교할 때 if 를 여러 번 쓰는 대신 case 가 깔끔합니다(다른 언어의 switch 와 비슷).
case "$x" in# x 값에 따라 갈라짐 0) echo "영";;# 0 이면 1) echo "하나";;# 1 이면 *) echo "그 외";; esac# * 는 나머지 전부for 는 목록/범위를, while 은 조건이 참인 동안, until 은 조건이 거짓인 동안 반복합니다. C 스타일 for 도 있습니다.
for ((i=1; i<=3; i++)); do echo "$i"; done# C 스타일 forwhile (( count < 3 )); do ((count++)); done# 조건이 참인 동안until (( count >= 3 )); do ((count++)); done# 조건이 거짓인 동안=~ 는 이 패턴에 맞는지 검사합니다. -e·-f·-d 등은 파일/폴더가 존재하는지, 어떤 종류인지 확인합니다.
if [[ "$email" =~ ^[a-z]+@[a-z]+\. ]]; then echo 맞음; fi# 정규식 매칭if [[ -f "$file" ]]; then echo "파일 있음"; fi# -f: 일반 파일인가if [[ -d "$dir" ]]; then echo "폴더 있음"; fi# -d: 폴더인가if [[ -z "$name" ]]; then echo "비었음"; fi# -z: 비어 있는가local 은 안에서만 쓰는 , 는 바꿀 수 없는 상수를 만듭니다. declare 는 정수(-i)·소문자(-l)·대문자(-u) 같은 성질을 지정합니다.
greet() { local msg="안녕"; echo "$msg $1"; }# msg 는 함수 밖에서 안 보임readonly PI=3.14# 바꿀 수 없는 상수declare -i num=42; num+=10# 정수형 → 계산이 자동(52)declare -u up="hi"; echo "$up"# 항상 대문자 → HI에 -v, -f 파일명 같은 을 받게 하는 표준 도구입니다. 글자 뒤 콜론(:)은 "값이 필요한 옵션"을 뜻합니다.
while getopts ":vf:" opt; do# v 는 값 없음, f 는 값 필요 case $opt in# 옵션별 분기 v) verbose=true ;;# -v 면 verbose 켜기 f) file="$OPTARG" ;; esac; done# -f 의 값은 source(또는 .)는 다른 파일을 현재 에서 실행해 ·설정을 불러옵니다. export 는 를 자식 에도 전달합니다.
source ./lib/helpers.sh# 다른 파일의 함수·변수를 현재 셸로. ~/.bashrc# . 은 source 의 짧은 형태export API_KEY="abc123"# 자식 프로세스도 볼 수 있게trap 은 가 (종료·오류·중단)를 받을 때 실행할 명령을 정합니다. 임시 파일 정리에 특히 유용합니다.
TMP=$(mktemp)# 안전한 임시 파일 만들기cleanup() { rm -f "$TMP"; }# 정리 trap cleanup EXIT# 스크립트가 끝나면 무조건 정리trap 'echo 중단됨; exit 1' SIGINT# Ctrl-C 눌러도 안전하게위쪽에 set 을 두면 오류에 강해집니다. -e(오류 시 중단)·-u(빈 금지)·-o pipefail( 실패 감지)을 함께 씁니다. -x 는 디버깅용.
set -euo pipefail# 견고한 스크립트의 표준 첫 줄set -x# 실행되는 명령을 하나씩 출력()set +x# 디버깅 끄기명령 뒤 & 를 붙이면 로 실행됩니다. jobs 로 목록, wait 로 끝날 때까지 기다립니다.
sleep 5 &# 백그라운드로 실행jobs# 실행 중인 백그라운드 작업 목록wait# 모든 백그라운드 작업이 끝날 때까지 대기time sleep 1# 명령이 걸린 시간 측정실전에서 반복되는 방어 패턴들입니다. 필수 값 확인, 명령 존재 확인, 실패 시 즉시 종료.
: "${VAR:?VAR 가 필요합니다}"# VAR 없으면 에러 내고 종료command -v jq && echo "jq 있음"# 명령이 설치됐는지 확인cp a b || { echo 실패; exit 1; }# 실패하면 메시지 내고 종료set -euo pipefail 은 세 의 결합입니다. 각각이 어떤 사고를 막는지 알면 왜 표준이 됐는지 이해됩니다.
set -e# 명령이 하나라도 실패하면 즉시 중단set -u# 정의 안 한 를 쓰면 에러(오타 방지)set -o pipefail# 중간이 실패해도 전체를 실패로로 파일 이름 매칭() 방식을 조절합니다. globstar 는 ** 로 , nullglob 은 매칭이 없으면 빈 값으로 처리합니다.
shopt -s globstar# ** 가 하위 폴더까지 매칭 ( 4+)for f in **/*.sh; do echo "$f"; done# 모든 하위의 .sh 파일shopt -s nullglob# 매칭 없으면 패턴 글자 대신 빈 값(내부 )는 단어를 나누는 기준입니다. 파일을 한 줄씩 안전하게 읽을 때 IFS= 와 read -r 을 함께 씁니다.
IFS=',' read -ra f <<< "a,b,c"# 쉼표로 나눠 f 에while IFS= read -r line; do# 공백·특수문자 보존하며 echo "$line"; done < file.txt# 한 줄씩 안전하게 읽기프로젝트마다 필요한 Node 버전이 다를 수 있습니다. 으로 여러 버전을 설치·전환합니다.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash# nvm 설치(버전 번호는 공식 문서 확인)nvm install 22# Node 22 설치nvm use 22# 현재 에서 Node 22 사용node -v# 전환된 버전 확인의 는 _modules/.bin 을 에 넣어 실행합니다. 없이도 프로젝트 도구를 쓸 수 있습니다.
npm init -y# package.json 빠르게 생성npm install lodash# 의존성 추가npm install -D typescript# 개발 전용 의존성npm run build# scripts.build 실행없이 최신 도구를 한 번만 돌릴 때 를 씁니다. 버전이 자주 바뀌는 에 특히 유용합니다.
npx create-next-app@latest my-app# 프로젝트 스캐폴딩 예시npx prettier --write .# 로컬/원격 prettier 실행npx --yes cowsay hello# 확인 없이 일회 실행공식 설치 또는 로 올립니다. 설치 직후 버전 명령으로 확인하세요.
curl -fsSL https://claude.ai/install.sh | bash# Claude (Anthropic)curl -fsSL https://chatgpt.com/codex/install.sh | sh# OpenAI Codex npm install -g @xai-official/grok# Grok CLI (npm 대안 예시)claude --version && codex --version# 설치 확인(예시)·인증·에 쓰는 와, 빠른 관리자 pnpm 도 자주 함께 설치합니다.
npm install -g firebase-tools# Firebase CLIfirebase login# 로 로그인firebase projects:list# 프로젝트 목록npm install -g pnpm# pnpm 설치는 됐는데 명령을 못 찾는다면 문제입니다. which 로 위치를 확인하고, 설정을 점검합니다.
which node npm# 실행 파일 위치echo "$PATH"# 검색 경로 확인npm config get prefix# command -v firebase || echo "not found"# 설치 여부 검사거의 모든 언어가 "를 로 받아 즉시 실행"하는 을 가집니다. 옵션 글자만 다를 뿐 쓰는 법은 똑같습니다.
python3 -c "import sys; print(sys.version)"# 한 줄node -e "console.log(1 + 1)"# 한 줄perl -e 'print "hello\n"'# 펄 한 줄ruby -e 'puts (1..5).to_a'# 루비 한 줄php -r 'echo PHP_VERSION;'# PHP 는 -r에게 수정을 부탁하면 거의 이 형태로 답이 옵니다. 파일을 읽어 을 바꿔 다시 쓰는 조각을 으로 넘기는 방식으로, assert 로 "바꿀 대상이 정말 있는지" 먼저 확인하는 것이 핵심입니다.
python3 - <<'PY'# 여기서부터 PY 까지가 파이썬 p = "src/app.py"# 고칠 파일 s = open(p, encoding="utf-8").read()# 통째로 읽기old = "before text"# 찾을 문자열(이 정의가 없으면 NameError)new = "after text"# 바꿀 문자열assert old in s# 바꿀 대상이 없으면 여기서 멈춘다(가장 중요)s = s.replace(old, new)# 치환open(p, "w", encoding="utf-8").write(s)# 다시 쓰기PY# 히어독 끝 — 줄 맨 앞에 정확히안에서 여러 줄짜리 설정·문서를 만들 때도 이 가장 깔끔합니다. 태그를 감싸지 않으면 $가 그 자리에서 채워집니다.
cat <<EOF > .env# 태그를 안 감싸면 변수가 채워진다PORT=$PORT# $PORT 가 실제 값으로 바뀌어 저장EOF# 여기서 끝cat <<'EOF' > template.txt# 감싸면 $PORT 가 bash <<< "echo one-liner"# 으로 한 줄만 넘기기주소(줄 번호·)를 앞에 붙이면 원하는 줄만 고칩니다. -i 로 파일을 직접 고칠 때는 -i.bak 처럼 를 붙이세요 — 백업이 남을 뿐 아니라 macOS 와 에서 똑같이 동작합니다.
sed -n '10,20p' log.txt# 10~20번째 줄만 출력sed '/^#/d' config.txt# # 로 시작하는 줄 삭제sed -i.bak 's/3000/8080/' config.txt# 백업(.bak)을 남기고 파일 수정sed -E 's/([a-z]+)@([a-z.]+)/\2 \/ \1/' mail.txt# 그룹으로 순서 바꾸기sed 's/error/ERROR/gI' log.txt# 무시하고 모두 치환printf 'appended\n' >> notes.txt# 마지막 줄 뒤에 (어디서나 통하는 방법)의 진가는 집계와 서식에서 드러납니다. 표를 읽어 항목별로 묶고 보기 좋게 출력하는 일이 한 줄로 끝납니다.
awk '{sum[$1] += $2} END {for (k in sum) printf "%-10s %5d\n", k, sum[k]}' sales.txt# 항목별 합계를 표로 출력awk -F, '{print $2}' data.csv# 는 -F, 로 쉼표 구분awk 'NF > 0' notes.txt# 빈 줄 제거(패턴만 쓰면 그 줄을 출력)awk '{n = split($0, a, "/"); print a[n]}' paths.txt# 에서 파일명만awk 'NR == FNR {m[$1] = $2; next} $1 in m {print $1, m[$1], $2}' a.txt b.txt# 두 파일 joinawk 'BEGIN {printf "%.2f\n", 22 / 7}'# BEGIN 만 쓰면 계산기은 로, "찾은 결과마다 명령 실행"은 로 처리합니다. 두 도구를 알면 로 이을 수 있는 범위가 크게 넓어집니다.
curl -s https://api.example.com/u | jq '.name'# JSON 에서 필드 하나jq -r '.items[] | .id' data.json# 을 줄 단위로 펼치기(-r 은 제거)ls *.txt | xargs wc -l# 찾은 파일마다 명령 실행grep -rlZ TODO . | xargs -0 sed -i.bak 's/TODO/DONE/g'# + 일괄 수정(-Z·-0 으로 공백 파일명까지 안전하게, 백업도 남긴다)* 와 + 는 가능한 한 길게 잡습니다(). 뒤에 ? 를 붙이면(*? · +?) 가능한 한 짧게 잡습니다(게으른 매칭) — 이것은 문법( -P · )에서만 됩니다. 기본·에서는 [^"]* 처럼 "그 글자가 아닌 것"으로 범위를 좁힙니다.
echo '<b>a</b><b>b</b>' | grep -Po '<b>.*</b>'# 탐욕적: 처음 <b> 부터 마지막 </b> 까지 한 덩어리echo '<b>a</b><b>b</b>' | grep -Po '<b>.*?</b>'# 게으른 매칭: <b>a</b> 와 <b>b</b> 를 따로grep -Eo '"[^"]*"' data.json# 확장 문법에서는 "가 아닌 글자"로 좁힌다grep -Po 'id=\K\d+' app.log# \K — 앞부분은 확인만 하고 숫자만 출력python3 -c "import re; print(re.findall(r'\d+(?=ms)', 'took 2300ms'))"# 전방 탐색 (?=…) — ms 바로 앞의 숫자만( ) 로 잡은 글을 패턴 안에서 \1 로 다시 부르면 "같은 글이 또 나오는 곳"을 찾을 수 있습니다. 실수로 두 번 친 낱말을 찾거나 고칠 때 씁니다.
grep -Ew '([a-z]+) \1' notes.txt# 연달아 두 번 나온 낱말(the the) 찾기sed -E 's/\b([a-z]+) \1\b/\1/g' notes.txt# 두 번 친 낱말을 하나로grep -E '^(.)(.).?\2\1$' words.txt# 앞뒤가 같은 5글자 이하 낱말(level · noon)sed -E 's/(.*)=(.*)/\2=\1/' config.txt# key=value 의 앞뒤 바꾸기같은 일을 운영체제마다 어떻게 하는지 나란히 비교해 보세요. ·macOS 는 · 를, 윈도우는 의 과 -replace 를 씁니다.
grep -rn -E 'TODO|FIXME' .# 리눅스·macOS: 폴더 안 모든 파일에서 찾기Select-String -Path *.txt -Pattern 'TODO|FIXME'# 윈도우 PowerShell: 같은 일sed -i.bak -E 's/[[:space:]]+$//' notes.txt# 리눅스·macOS 공통: 줄 끝 공백 지우기(백업 .bak 을 남긴다)(Get-Content notes.txt) -replace '\s+$', '' | Set-Content notes.txt# 윈도우 PowerShell: 같은 일findstr /R /C:"^[0-9][0-9]*$" numbers.txt# 윈도우 : 숫자만 있는 줄(+ 가 없어 [0-9][0-9]* 로)(rg)은 보다 빠르고, \d 를 그대로 알며, 에 적힌 파일을 알아서 건너뜁니다(brew install ripgrep · apt install ripgrep). 은 macOS·에 처음부터 있는 의 원조이고, 은 의 와 기록을 으로 찾습니다.
rg -n 'TODO|FIXME'# 아래 전부, 줄 번호와 함께rg -o '\d{4}-\d{2}-\d{2}' -g '*.log'# .log 파일에서 날짜만perl -pe 's/(\d+)-(\d+)/$2-$1/g' a.txt# 펄: 12-34 → 34-12perl -pi -e 's/foo/bar/g' *.txt# 펄: 여러 파일을 바로 고치기git log --grep='fix.*login' -i --oneline# 메시지를 정규식으로 찾기git log -G 'apiKey' --oneline# 코드 변경 내용을 정규식으로 찾기의 re 는 문법이라 \d \w \s, 게으른 매칭, 이름 붙인 묶음까지 모두 됩니다. 패턴은 r"…" 원시 로 쓰는 것이 기본입니다 — 그냥 "\b" 라고 쓰면 백스페이스 글자로 바뀝니다.
import re# 모듈 불러오기re.search(r"\d+", "a12b").group()# 처음 맞는 것 하나 → "12"re.findall(r"\d+", "a12b345")# 맞는 것 모두 → ["12", "345"]re.sub(r"\s+", " ", "a b")# 바꾸기 → "a b"re.split(r"[,;]\s*", "a, b;c")# 정규식으로 자르기 → ["a", "b", "c"]m = re.match(r"(?P<y>\d{4})-(?P<m>\d{2})", "2026-10")# 이름 붙인 묶음 — m["y"] 는 "2026"pat = re.compile(r"error", re.I)# 미리 만들어 두기, re.I 는 무시는 을 씁니다. /패턴/ 은 줄 전체를, $3 ~ /패턴/ 은 그 열만 검사하고, gsub 로 바꿉니다. -F 에 을 주면 여러 로 한꺼번에 자를 수 있습니다.
awk '/ERROR|WARN/' app.log# -E 와 같은 일awk '$4 ~ /^user=a/' app.log# 4이 user=a 로 시작하는 줄awk '$3 !~ /INFO/ {print $3, $4}' app.log# INFO 가 아닌 줄의 3·4번째 열awk '{gsub(/[0-9]+ms/, "N ms"); print}' app.log# 줄 안의 2300ms 같은 글을 모두 바꾸기awk -F'[=: ]+' '{print $2}' config.txt# = · : · 공백 여러 개를 모두 구분자로Learn X in Y Minutes (Bash, CC BY-SA)를 참고해 재구성했습니다. 일부 명령은 개념 참고용이에요.