๐งญ Bash ๋ฉํ๋ฌธ์ (Metacharacter)
๋ฉํ๋ฌธ์(Metacharacter)๋ Bash์์ ํน๋ณํ ์๋ฏธ๋ฅผ ๊ฐ๋ ๊ธฐํธ๋ฅผ ๋งํ๋ค.
ํ์ผ๋ช ํ์ฅ(globbing), ๋ช ๋ น ์คํ, ๋ณ์ ์นํ, ๋ฐฑ๊ทธ๋ผ์ด๋ ์ฒ๋ฆฌ ๋ฑ ๋ค์ํ ๊ธฐ๋ฅ์ ์ํํ๋ค.
๐ 1) * (Asterisk)
| ์๋ฏธ | 0๊ฐ ์ด์์ ์์์ ๋ฌธ์์ ๋งค์นญ |
| ํน์ง | - ์จ๊น ํ์ผ(.์ผ๋ก ์์ํ๋ ํ์ผ)์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋งค์นญ๋์ง ์์ - ์๋ธ ๋๋ ํฐ๋ฆฌ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ๊ท์ ์ผ๋ก ํ์ํ์ง ์์ - ์์๋ฐ์ดํ(')๋ ํฐ๋ฐ์ดํ(")๋ก ๊ฐ์ธ๋ฉด ๊ธ์ ๊ทธ๋๋ก ์ธ์ |
$ ls
a.txt b.txt c.log .hidden
$ echo *.txt
a.txt b.txt # .hidden์ ํฌํจ๋์ง ์์
$ echo "*.txt"
*.txt # ๋ฐ์ดํ๋ก ๊ฐ์ธ๋ฉด ์์ผ๋์นด๋๊ฐ ๋์ํ์ง ์์
$ echo **/*.txt
dir1/a.txt dir2/b.txt # (bash 4 ์ด์ + globstar ์ต์
์ผ ๋๋ง ์ฌ๊ท ํ์)
โ 2) ? (Question mark)
| ์๋ฏธ | ์ ํํ ํ ๊ธ์์ ๋งค์นญ |
| ํน์ง | ์จ๊น ํ์ผ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ธ๋จ. ๋ฌธ์ ์๊ฐ ๊ณ ์ ๋ ํ์ผ๋ช ์ ์ฐพ์ ๋ ์ ์ฉํจ. ์๋ฆฟ ์ ๊ณ ์ ํจํด์ ๋ง๋ค ๋๋ ์ ์ฉํ์ง๋ง, ๋ค๊ตญ์ด(UTF-8) ๋ ์ด๋ชจ์ง ๋ฑ ์ผ๋ถ ์ ธ/๋ก์ผ์ผ์์ 'ํ ๋ฌธ์'์ ์ ์๊ฐ locale ์ค์ ์ ๋ฐ๋ผ ์ฒด๊ฐ๊ณผ ๋ค๋ฅผ ์ ์๋ค. |
์๋ฅผ ๋ค์ด 'file?.txt'๋ 'file1.txt', 'fileA.txt'์ ๋งค์นญํ์ง๋ง 'file10.txt'๋ ๋ถ์ผ์นํ๋ค.
$ ls
file1.txt file2.txt file10.txt fileA.txt
$ echo file?.txt
file1.txt file2.txt fileA.txt # file10.txt๋ ๋ถ์ผ์น
๐ฒ 3) $ (Dollar sign)
| ์๋ฏธ | ๋ณ์, ๋ช ๋ น, ์์์ ๊ฒฐ๊ณผ๋ฅผ ๋ฌธ์์ด๋ก ์นํ |
| ์ฌ์ฉ ํํ | - ๋ณ์ ์นํ: $var ๋๋ ${var} - ๋ช ๋ น ์นํ: $(command) → ๋ช ๋ น์ ์ถ๋ ฅ ๊ฒฐ๊ณผ๋ก ๋์ฒด - ์ฐ์ ์นํ: $((expression)) → ์ ์ ์ฐ์ฐ ๊ฒฐ๊ณผ๋ก ๋์ฒด |
| ํน์ ๋ณ์ | $? (์ง์ ๋ช ๋ น์ ์ข ๋ฃ ์ฝ๋), $! (๋ฐฑ๊ทธ๋ผ์ด๋ PID), $$ (ํ์ฌ ์ ธ PID), $@ (๋ชจ๋ ์ธ์) ๋ฑ |
์์ ์ ์ํด '"${var}"'์ฒ๋ผ ํฐ ๋ฐ์ดํ๋ฅผ ์ ๋ ๊ฒ์ด ์ข๋ค.
ํน์ ํ๋ผ๋ฏธํฐ๋ก๋ ์ง์ ์ข ๋ฃ์ฝ๋ '$?', ์ง์ ๋ฐฑ๊ทธ๋ผ์ด๋ PID '$!', ํ์ฌ ์ ธ PID '$$$', ์ธ์ ๋ณด์กด ์ ๋ฌ '$@' ๋ฑ์ด ์๋ค.
$ name="Linux"
$ echo "Hello, $name"
Hello, Linux
$ echo "Home: ${HOME}"
Home: /home/user
$ echo "Today: $(date +%Y-%m-%d)"
Today: 2025-10-21
$ echo $((3 + 7))
10
$ false
$ echo $?
1 # ์ด์ ๋ช
๋ น์ ์ข
๋ฃ ์ฝ๋ (0=์ฑ๊ณต, 1=์คํจ)
๐ก TIP: ๋ณ์ ์นํ ์ "${var}"์ฒ๋ผ ํฐ๋ฐ์ดํ๋ก ๊ฐ์ธ๋ฉด ๊ณต๋ฐฑ์ด ์๋ ๊ฐ๋ ์์ ํ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ค.
HOME์ ํ๊ฒฝ ๋ณ์, ํ์ฌ ๋ก๊ทธ์ธ ์ฌ์ฉ์์ ํ ๋๋ ํฐ๋ฆฌ ๊ฒฝ๋ก๋ฅผ ๋ปํ๋ค.
data +%Y-%m-%d๋ ์ค๋ ๋ ์ง๋ฅผ "์ฐ-์-์ผ" ํ์์ผ๋ก ์ถ๋ ฅํ๋ผ๋ ์๋ฏธ
๐งฉ $?
| ์๋ฏธ | ์ง์ ๋ช ๋ น์ ์ข ๋ฃ ์ํ ์ฝ๋(exit status) |
| ๊ฐ | 0 = ์ฑ๊ณต, 0์ด ์๋ = ์คํจ |
| ์ฌ์ฉ ๋ชฉ์ | ์กฐ๊ฑด๋ฌธ(if, &&, ` |
๐ ์์
$ ls /tmp
# (์ฑ๊ณต)
$ echo $?
0 # ์ฑ๊ณต(0)
$ ls /no/such/path
ls: cannot access '/no/such/path': No such file or directory
$ echo $?
2 # ์คํจ(2)
๐ก ํ๋ก๊ทธ๋จ์ด ๋๋ ๋ return ๊ฐ์ด๋ exit() ์ฝ๋๊ฐ ์ฌ๊ธฐ ์ ์ฅ๋ฉ๋๋ค.
๐งฉ 4๏ธโฃ #! (Shebang, ์๋ฑ )
| ์๋ฏธ | “์ด ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ ๋ ์ด๋ค ํ๋ก๊ทธ๋จ(์ธํฐํ๋ฆฌํฐ)์ ์ธ์ง” ์ง์ |
| ์์น | .sh ํ์ผ์ ๋งจ ์ฒซ ์ค์๋ง ์ฌ์ฉ |
| ์ด๋ฆ | Shebang (# + !) |
๐ ์์: hello.sh
#!/bin/bash
echo "Hello Shell"
์คํ
$ ./hello.sh
Hello Shell
๐ก #!/bin/bash ๋ผ๊ณ ์ ์ผ๋ฉด “์ด ํ์ผ์ bash๋ก ์คํํด๋ผ”๋ ๋ป์ด์์.
Python ์คํฌ๋ฆฝํธ๋ #!/usr/bin/python3์ฒ๋ผ ์๋๋ค.
๐งฉ 5๏ธโฃ ## (๋ฌธ์์ด ์๋ผ๋ด๊ธฐ — Prefix ์ ๊ฑฐ)
| ํํ | ${๋ณ์##ํจํด} |
| ๊ธฐ๋ฅ | ๋ณ์์ ๊ฐ์์ ๊ฐ์ฅ ๊ธด ์ ๋์ฌ(prefix) ๋ฅผ ํจํด์ผ๋ก ์ ๊ฑฐ |
| ๋ฐ๋ ๊ธฐ๋ฅ | ${๋ณ์#ํจํด} → ๊ฐ์ฅ ์งง์ ์ ๋์ฌ ์ ๊ฑฐ |
๐ ์์
$ path="/home/user/docs/report.txt"
$ echo ${path#*/}
home/user/docs/report.txt # ์ฒซ '/' ์๋ถ๋ถ ์ ๊ฑฐ (์งง์ ์ ๊ฑฐ)
$ echo ${path##*/}
report.txt # ๋ง์ง๋ง '/' ์๋ถ๋ถ๊น์ง ์ ๊ฑฐ (๊ธด ์ ๊ฑฐ)
๐ก #์ “์์์๋ถํฐ ์๋ฅด๊ธฐ”,
##๋ “์์์ ๊ฐ์ฅ ๋ง์ด ์๋ฅด๊ธฐ”์ ์๋ฏธ์์.
๐งฉ 6๏ธโฃ $@ (๋ชจ๋ ์ธ์)
| ์๋ฏธ | ์คํฌ๋ฆฝํธ๋ ํจ์๋ก ์ ๋ฌ๋ ๋ชจ๋ ์ธ์(arguments) |
| ํํ | $1, $2, $3... ๊ฐ๊ฐ์ ์ธ์ ๊ฐ๋ณ ์ ๊ทผ๋ ๊ฐ๋ฅ |
| ์ฐจ์ด์ | $@์ $*๋ ์ ์ฌํ์ง๋ง, ๋ฐ์ดํ ์ฒ๋ฆฌ ๋ฐฉ์์ด ๋ค๋ฆ |
๐ ์์
#!/bin/bash
echo "๋ชจ๋ ์ธ์: $@"
echo "์ฒซ ๋ฒ์งธ: $1"
echo "์ธ์ ์: $#"
์คํ
$ ./test.sh apple banana cherry
๋ชจ๋ ์ธ์: apple banana cherry
์ฒซ ๋ฒ์งธ: apple
์ธ์ ์: 3
๐ก $#๋ ์ธ์์ “๊ฐ์(count)”๋ฅผ ์๋ฏธํฉ๋๋ค.
$*์ $@๋ ๋ ๋ค “์คํฌ๋ฆฝํธ๋ ํจ์์ ์ ๋ฌ๋ ๋ชจ๋ ์ธ์(arguments)” ๋ฅผ ์๋ฏธํ์ง๋ง,
๋ฐ์ดํ(" ")๋ก ๊ฐ์ ๋ ๋์์ด ๋ค๋ฆ
๋๋ค.
๐งฉ 1๏ธโฃ ๊ธฐ๋ณธ ๊ฐ๋
| $* | ๋ชจ๋ ์ธ์๋ฅผ ํ๋์ ๋ฌธ์์ด๋ก ์ทจ๊ธ |
| $@ | ๋ชจ๋ ์ธ์๋ฅผ ๊ฐ๊ฐ์ ๋ ๋ฆฝ๋ ๋ฌธ์์ด๋ก ์ทจ๊ธ |
์ฆ, " "(๋ฐ์ดํ) ์์์ ์ฐ๋๋์ ๋ฐ๋ผ ์์ ํ ๋ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ ๋์ต๋๋ค ๐
๐ 2๏ธโฃ ์์ ์ฝ๋ (args.sh)
#!/bin/bash
echo '--- "$*" ์ถ๋ ฅ ---'
for arg in "$*"; do
echo "[$arg]"
done
echo '--- "$@" ์ถ๋ ฅ ---'
for arg in "$@"; do
echo "[$arg]"
done
๐ก 3๏ธโฃ ์คํ ๊ฒฐ๊ณผ
$ bash args.sh apple banana "cherry pie"
์ถ๋ ฅ:
--- "$*" ์ถ๋ ฅ ---
[apple banana cherry pie] ← ํ๋์ ๋ฌธ์์ด๋ก ์ธ์
--- "$@" ์ถ๋ ฅ ---
[apple]
[banana]
[cherry pie] ← ๊ฐ ์ธ์๊ฐ ๋ฐ๋ก ์ ์ง๋จ
โ๏ธ 4๏ธโฃ ์ ๋ฆฌ ์์ฝ
| $* | ๋ชจ๋ ์ธ์๋ฅผ “ํ๋์ ๋ฌธ์์ด”๋ก ํฉ์นจ | "apple banana cherry pie" | "${1} ${2} ${3}" ์ฒ๋ผ ํฉ์ณ์ง |
| $@ | ๋ชจ๋ ์ธ์๋ฅผ “๊ฐ๋ณ ์ธ์”๋ก ์ ์ง | "apple" "banana" "cherry pie" | ์ธ์ ๊ตฌ๋ถ์ด ๊ทธ๋๋ก ์ ์ง๋จ |
๐ง 5๏ธโฃ ์ธ์ ๋ฌด์์ ์จ์ผ ํ ๊น?
- "$@" → โ
๋๋ถ๋ถ์ ๊ฒฝ์ฐ์ ์ฌ์ฉ (๊ถ์ฅ)
→ ์ธ์์ ๊ณต๋ฐฑ์ด ํฌํจ๋์ด ์์ด๋ ์ ํํ๊ฒ ์ฒ๋ฆฌํจ. - "$*" → โ ๏ธ ๊ฑฐ์ ์ฐ์ด์ง ์์
→ ์ธ์๋ค์ด ํ ์ค๋ก ํฉ์ณ์ ธ์, ๊ตฌ๋ถ์ด ์ฌ๋ผ์ง.
๐ 6๏ธโฃ ์ถ๊ฐ ์ค์ต (์ฐจ์ด ๋ช ํํ๊ฒ ๋ณด๊ธฐ)
#!/bin/bash
echo 'Using "$*":'
printf "%s\n" "$*"
echo 'Using "$@":'
printf "%s\n" "$@"
์คํ
$ bash test.sh "New York" Seoul Paris
์ถ๋ ฅ
Using "$*":
New York Seoul Paris
Using "$@":
New York
Seoul
Paris
โ ๊ฒฐ๋ก ์์ฝ
| ์๋ฏธ | ๋ชจ๋ ์ธ์ | ๋ชจ๋ ์ธ์ |
| ๋ฐ์ดํ ์์์ | ์ ์ฒด๋ฅผ ํ๋์ ๋ฌธ์์ด๋ก | ๊ฐ๊ฐ์ ๋ ๋ฆฝ๋ ์ธ์๋ก |
| ๊ณต๋ฐฑ ํฌํจ ์ธ์ ์ฒ๋ฆฌ | ๊นจ์ง | ์์ |
| ์ถ์ฒ ์ฌ๋ถ | โ | โ (ํญ์ ์ด๊ฑธ ์จ๋ผ!) |
โ ํ ์ค ์์ฝ
"${@}"๋ “์ธ์๋ฅผ ๊ทธ๋๋ก ์ ์งํด์ ์ ๋ฌ”,
"${*}"๋ “์ธ์๋ค์ ๊ณต๋ฐฑ์ผ๋ก ์ด์ด๋ถ์ฌ ํ ๋ฌธ์์ด๋ก ๋ง๋ฆ”.
์ค๋ฌด๋ ์คํฌ๋ฆฝํธ์์๋ ํญ์ "$@"๋ฅผ ์ฐ๋ ๊ฒ ์์ ํฉ๋๋ค.
๐ง ์ถ๊ฐ๋ก ์์๋๋ฉด ์ข์ $ ๊ด๋ จ ํน์ ํ๋ผ๋ฏธํฐ
| $0 | ํ์ฌ ์คํ ์ค์ธ ์คํฌ๋ฆฝํธ ์ด๋ฆ | /home/user/script.sh |
| $1~$9 | ์ฒซ ๋ฒ์งธ~์ํ ๋ฒ์งธ ์ธ์ | $1=์ฒซ ์ธ์ |
| $# | ์ธ์ ๊ฐ์ | 3 |
| $@ | ๋ชจ๋ ์ธ์ (๊ณต๋ฐฑ ๊ตฌ๋ถ) | arg1 arg2 arg3 |
| $* | ๋ชจ๋ ์ธ์ (ํ๋์ ๋ฌธ์์ด๋ก) | "arg1 arg2 arg3" |
| $? | ์ง์ ๋ช ๋ น์ ์ข ๋ฃ ์ํ | 0 ๋๋ ๋น0 |
| $$ | ํ์ฌ ์ ธ์ PID(Process ID) | ์: 3482 |
| $! | ๋ง์ง๋ง ๋ฐฑ๊ทธ๋ผ์ด๋ ํ๋ก์ธ์ค์ PID | ์: 4521 |
โ๏ธ 4) & (Ampersand)
| ์๋ฏธ | ๋ช ๋ น์ด๋ฅผ ๋ฐฑ๊ทธ๋ผ์ด๋ ํ๋ก์ธ์ค๋ก ์คํ |
| ํน์ง | ๋ช ๋ น ๋์ &๋ฅผ ๋ถ์ด๋ฉด ์ ธ์ ์ฆ์ ํ๋กฌํํธ๋ฅผ ๋ฐํํ๊ณ , ๋ช ๋ น์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๊ณ์ ์คํ๋จ. |
‘’cmd &”๊ณผ ๊ฐ์ ํํ๋ก ์ฌ์ฉํ๋ค.
$ sleep 5 &
[1] 2345 # [์์
๋ฒํธ] [PID]
$ echo "Running in background"
Running in background
$ jobs
[1]+ Running sleep 5 &
$ fg
sleep 5 # ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ ํฌ๊ทธ๋ผ์ด๋๋ก ๋ณต๊ท
โ ์ ๋ฆฌ ์์ฝ
| * | 0๊ฐ ์ด์ ์์์ ๋ฌธ์ | ํ์ผ๋ช ๋งค์นญ (์์ผ๋์นด๋) | ์จ๊น ํ์ผ์ ๋งค์นญ ์ ๋จ |
| ? | ์ ํํ ํ ๋ฌธ์ | ์๋ฆฌ์ ๊ณ ์ ๊ฒ์ | ๋ค๊ตญ์ด ํ๊ฒฝ์์๋ “ํ ๊ธ์” ์ ์ ์ฃผ์ |
| $ | ๋ณ์, ๋ช ๋ น, ์ฐ์ ์นํ | ๋์ ๊ฐ ์ถ๋ ฅ | ํฐ๋ฐ์ดํ๋ก ๊ฐ์ธ์ ์์ ํ๊ฒ ์ฌ์ฉ |
| & | ๋ฐฑ๊ทธ๋ผ์ด๋ ์คํ | ๋น๋๊ธฐ ๋ช ๋ น ์ํ | PID ๋ฐ ์ข ๋ฃ ์ฝ๋ ํ์ธ ํ์ |
โ ์ต์ข ์ ๋ฆฌ ๋ฌธ์ฅ
Bash ๋ฉํ๋ฌธ์๋ ๋จ์ํ ๊ธฐํธ๊ฐ ์๋๋ผ,
์ ธ์์ ํ์ผ ๊ฒ์·๋ณ์ ์นํ·ํ๋ก์ธ์ค ์ ์ด๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋ ํต์ฌ ๊ธฐ๋ฅ์ด๋ค.
ํนํ *, ?, $, &๋ ์ค๋ฌด ์คํฌ๋ฆฝํธ ์์ฑ์์ ๊ฐ์ฅ ์์ฃผ ์ฌ์ฉ๋๋ ๊ธฐ๋ณธ ๋ฉํ๋ฌธ์์ด๋ฏ๋ก ๋ฐ๋์ ์ตํ๋์ด์ผ ํ๋ค.
๐ฃ๏ธ echo ๋ช ๋ น์ด
โ ๊ฐ์
echo๋ ๋ฌธ์์ด์ ์ถ๋ ฅํ๋ ๋ช
๋ น์ด์์.
์
ธ์์ ํ๋ฉด์ ๋ฉ์์ง๋ฅผ ๋ณด์ฌ์ฃผ๊ฑฐ๋, ๋ณ์์ ๊ฐ์ ํ์ธํ ๋ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋ฉ๋๋ค.
๐งฉ ๊ธฐ๋ณธ ๋ฌธ๋ฒ
echo [์ต์
] [๋ฌธ์์ด]
๐ ์์ 1 — ๋จ์ ๋ฌธ์์ด ์ถ๋ ฅ
$ echo Hello, world!
Hello, world!โ
๐ ์์ 2 — ๋ณ์ ์ถ๋ ฅ
$ name="Alice"
$ echo $name
Alice
๐ก $name ๋์ "${name}"์ฒ๋ผ ์ฐ๋ฉด, ๊ฐ ์์ ๊ณต๋ฐฑ์ด ์์ด๋ ์์ ํด์.
๐ ์์ 3 — ์ค๋ฐ๊ฟ ์์ด ์ถ๋ ฅ
$ echo -n "No newline"
No newline$
(-n ์ต์ ์ ์ถ๋ ฅ ํ ์ค๋ฐ๊ฟ์ ํ์ง ์์)
๐ ์์ 4 — ์ ์ด๋ฌธ์(์ด์ค์ผ์ดํ ์ํ์ค) ์ฒ๋ฆฌ
$ echo -e "line1\nline2"
line1
line2
(-e ์ต์ ์ ๋ถ์ด๋ฉด \n, \t ๊ฐ์ ์ ์ด๋ฌธ์๋ฅผ ์ธ์ํฉ๋๋ค.)
โ ์ฃผ์ ์ต์ ์์ฝ
| -n | ์ค๋ฐ๊ฟ ์์ด ์ถ๋ ฅ |
| -e | ์ด์ค์ผ์ดํ ๋ฌธ์(\n, \t ๋ฑ) ํด์ |
| -E | (๊ธฐ๋ณธ๊ฐ) ์ด์ค์ผ์ดํ ๋ฌธ์ ํด์ํ์ง ์์ |
๐ก ํ์ฉ ์์
$ echo "ํ์ฌ ๊ฒฝ๋ก: $(pwd)"
ํ์ฌ ๊ฒฝ๋ก: /home/user
Bash์์์ C์ธ์ด printf() ๋ฌธ๋ฒ
์ด๊ฑด Bash์์ C ์ธ์ด์ printf() ๋ฌธ๋ฒ์ ๊ทธ๋๋ก ์ด ๋ช
๋ น์ด์์.
์๋์ ์์ ํ ํ์ด์ ์ค๋ช
ํด์ค๊ฒ์ ๐
๐งฉ printf "%s\n" "$*" ์ ๊ตฌ์กฐ ๋ถ์
1๏ธโฃ printf ๋ช ๋ น์ด๋?
Bash์ printf๋ C ์ธ์ด์ printf() ํจ์์ ๊ฑฐ์ ๋์ผํ ํ์ ์ง์ ์ถ๋ ฅ ํจ์์์.
echo๋ณด๋ค ๋ ์ ๋ฐํ๊ฒ ํฌ๋งท(ํ์)์ ์ ์ดํ ์ ์์ต๋๋ค.
๐ ๊ธฐ๋ณธ ๋ฌธ๋ฒ
printf "ํ์(format)" ์ธ์1 ์ธ์2 ...
2๏ธโฃ " %s\n "์ ์๋ฏธ
์ด๊ฑด **์ถ๋ ฅ ํ์ ๋ฌธ์์ด(format string)**์ด์์.
C์ธ์ด์ ๊ฐ์ ๊ท์น์ ๋ฐ๋ฆ
๋๋ค.
| %s | ๋ฌธ์์ด(string) ํ๋๋ฅผ ์ถ๋ ฅํ๋ผ |
| \n | ์ค๋ฐ๊ฟ(newline)์ ๋ฃ์ด๋ผ |
์ฆ " %s\n "์
“๋ฌธ์์ด ํ๋๋ฅผ ์ถ๋ ฅํ๊ณ ์ค๋ฐ๊ฟํด๋ผ”
๋ ๋ป์ด์์.