리눅스, macOS 또는 다른 유닉스 기반 시스템에서 Bash 셸을 능숙하게 다루려면 특수 문자, 예를 들어 ~, *, |, > 등을 숙지하는 것이 필수적입니다. 이 글에서는 이러한 복잡한 리눅스 명령들을 쉽게 이해하고, 특수 문자들을 자유자재로 활용할 수 있도록 안내합니다.
특수 문자란 무엇인가?
Bash 셸은 특정 문자들을 두 가지 방식으로 처리합니다. 셸에 입력된 특수 문자는 그 자체로 명령처럼 작동하며, 셸에게 특정 기능을 수행하도록 지시합니다. 이것은 마치 단일 문자 명령과 같습니다.
때로는 이러한 문자들의 마법 같은 기능을 사용하지 않고 단순히 문자를 출력해야 할 때도 있습니다. 특수 문자 기능을 사용하지 않고 문자를 그대로 표시하는 방법도 존재합니다.
어떤 문자들이 ‘특수’ 또는 ‘메타’ 문자인지, 그리고 그 문자들이 기능적으로 사용될 수 있는지, 아니면 문자 그대로 사용될 수 있는지 알아보겠습니다.
~: 홈 디렉토리
물결표(~)는 홈 디렉토리를 축약하여 표현한 것입니다. 다시 말해, 명령을 입력할 때 홈 디렉토리의 전체 경로를 입력하는 번거로움을 피할 수 있습니다. 파일 시스템 어디에서든 이 명령을 사용하여 홈 디렉토리로 쉽게 이동할 수 있습니다.
cd ~
이 명령은 상대 경로와 함께 사용할 수도 있습니다. 예를 들어, 홈 폴더가 아닌 파일 시스템의 다른 위치에서 현재 작업 디렉토리의 하위 디렉토리로 이동하고 싶을 때, 물결표를 사용하여 쉽게 이동할 수 있습니다.
cd ~/work/archive
.: 현재 디렉토리
마침표(.)는 현재 디렉토리를 가리킵니다. `ls` 명령과 `-a` (all) 옵션을 함께 사용하면 디렉토리 목록에서 현재 디렉토리를 확인할 수 있습니다.
ls -a
명령에 마침표를 사용하여 현재 디렉토리의 경로를 나타낼 수도 있습니다. 예를 들어, 현재 디렉토리에 있는 스크립트를 실행하려면 다음과 같이 호출합니다.
./script.sh
이는 Bash에게 현재 디렉토리에서 `script.sh` 파일을 찾도록 지시합니다. 이렇게 하면 실행 파일이나 스크립트가 저장된 디렉토리를 검색하지 않고 현재 디렉토리에서만 파일을 찾습니다.
..: 부모 디렉토리
이중 마침표, 또는 ‘두 개의 점'(..)은 현재 디렉토리의 상위 디렉토리를 나타냅니다. 이를 사용하여 디렉토리 구조에서 한 단계 위로 이동할 수 있습니다.
cd ..
예를 들어, 디렉토리 구조에서 한 단계 위로 이동한 다음, 그 위치에서 다른 디렉토리로 들어가고 싶을 때 이 명령을 상대 경로와 함께 사용할 수 있습니다.
또한 이 기술을 사용하여 현재 디렉토리와 같은 레벨의 디렉토리 트리로 빠르게 이동할 수도 있습니다. 한 단계 위로 이동한 후 다른 디렉토리로 다시 내려가는 방식입니다.
cd ../gc_help
/: 경로 디렉토리 구분자
슬래시(/), 또는 단순히 슬래시라고 불리는 이 기호는 경로 이름에서 디렉토리들을 구분하는 데 사용됩니다.
ls ~/work/archive
하나의 슬래시(/)는 가장 짧은 디렉토리 경로를 나타내며, 리눅스 디렉토리 트리의 모든 항목이 루트 디렉토리에서 시작되기 때문에 이 명령을 사용하여 루트 디렉토리로 빠르게 이동할 수 있습니다.
cd /
#: 주석 처리 또는 문자열 자르기
대부분의 경우, 해시 기호(#)는 셸에게 그 뒤에 오는 내용이 주석이며 실행할 필요가 없음을 알리는 데 사용됩니다. 이는 셸 스크립트에서 유용하며 명령줄에서도 사용할 수 있지만 자주 사용되지는 않습니다.
# This will be ignored by the Bash shell
하지만 이 주석은 명령 기록에는 추가되므로 완전히 무시되지는 않습니다.
또한 해시 기호를 사용하여 문자열 변수를 자르고, 문자열의 앞부분을 제거할 수도 있습니다. 다음 예시에서는 `this_string`이라는 문자열 변수를 생성합니다.
그리고 이 변수에 “Dave Geek!”이라는 텍스트를 할당합니다.
this_string="Dave Geek!"
다음 명령은 `echo`를 사용하여 터미널 창에 “How-To”라는 단어를 출력합니다. 그리고 매개변수 확장을 통해 문자열 변수에 저장된 값을 검색합니다. 해시 기호와 텍스트 “Dave”를 추가함으로써 문자열의 해당 부분을 잘라낸 후 `echo`에 전달합니다.
echo How-To ${this_string#Dave}
이것은 문자열 변수에 저장된 값을 변경하지 않습니다. 오직 `echo`로 전달되는 내용에만 영향을 미칩니다. `echo`를 사용하여 문자열 변수의 값을 다시 출력해 보면 변수의 값이 변경되지 않았음을 확인할 수 있습니다.
echo $this_string
?: 단일 문자 와일드카드
Bash 셸은 세 가지 와일드카드를 지원하며, 그 중 하나가 물음표(?)입니다. 와일드카드는 파일 이름 패턴에서 문자를 대체하는 데 사용됩니다. 와일드카드가 포함된 파일 이름은 하나의 파일 이름이 아닌 여러 파일 이름과 일치하는 패턴을 형성합니다.
물음표 와일드카드는 정확히 하나의 문자를 나타냅니다. 다음 파일 이름 패턴을 살펴보겠습니다.
ls badge?.txt
이것은 “이름이 ‘badge’로 시작하고 파일 이름 확장자 앞에 단일 문자가 오는 모든 파일을 나열합니다.”라고 해석할 수 있습니다.
다음과 같은 파일들과 일치합니다. 파일 이름의 “badge” 부분 뒤에 숫자가 있는 파일도 있고, 문자가 있는 파일도 있습니다. 물음표 와일드카드는 문자와 숫자 모두에 일치합니다.
하지만 이 파일 이름 패턴은 “badge.txt”와는 일치하지 않습니다. 왜냐하면 파일 이름 “badge”와 파일 확장자 사이에 단일 문자가 없기 때문입니다. 물음표 와일드카드는 반드시 파일 이름의 해당 위치에 문자와 일치해야 합니다.
또한 물음표를 사용하여 파일 이름에 특정 개수의 문자가 포함된 모든 파일을 찾을 수 있습니다. 다음은 파일 이름에 정확히 다섯 글자가 포함된 모든 텍스트 파일을 나열합니다.
ls ?????.txt
*: 문자 시퀀스 와일드카드
별표(*)는
ls badge*
와일드카드는 0개 이상의 모든 문자 시퀀스를 나타냅니다. 다음 파일 이름 패턴을 살펴보겠습니다.
별표 와일드카드는 문자의 시퀀스나 아무 문자도 없을 수 있기 때문에 “badge.txt”와 일치합니다.
ls source.*
[]: 문자 집합 와일드카드
앞서 설명했듯이 물음표는 단일 문자를 나타내고, 별표는 모든 문자 시퀀스(문자가 없을 수도 있음)를 나타냅니다. 반면에 대괄호([])는 괄호 안에 포함된 문자 중 하나와 일치하는 단일 문자를 나타냅니다. 파일 이름의 해당 문자는 와일드카드 문자 집합의 문자 중 하나 이상과 일치해야 합니다.
ls badge_0[246].txt
ls badge_[01][789].txt
ls badge_[23][1-5].txt
;: 셸 명령 구분 기호
ls > count.txt; wc -l count.txt; rm count.txt
두 번째 명령은 첫 번째 명령이 실패하더라도 실행되며, 세 번째 명령은 두 번째 명령이 실패하더라도 실행됩니다.
cd ./doesntexist && cp ~/Documents/reports/* .
&: 백그라운드 프로세스
터미널 창에 명령을 입력하면 명령이 완료될 때까지 프롬프트가 나타나지 않습니다. 일반적으로 이 작업은 1~2분 정도 걸립니다. 하지만 gedit과 같은 다른 응용 프로그램을 실행하면 응용 프로그램을 닫을 때까지 터미널 창을 사용할 수 없게 됩니다.
gedit command_address.page &
Bash는 시작된 프로세스의 ID를 표시한 다음 명령줄로 돌아갑니다. 그러면 터미널 창을 계속 사용할 수 있습니다.
sort < words.txt
명령의 입력이 리디렉션되면 이름이 지정된 파일에서 읽을 때와 다르게 작동할 수 있습니다.
`wc`를 사용하여 파일의 단어, 줄 및 문자 수를 계산하면 값과 파일 이름이 인쇄됩니다. 파일 내용을 `wc`로 리디렉션하면 동일한 숫자 값이 출력되지만 데이터가 나온 파일의 이름을 알 수 없으므로 파일 이름을 출력할 수 없습니다.
다음은 `wc`를 사용하는 몇 가지 예입니다.
wc words.txt
wc < words.txt
>: 출력 리디렉션
오른쪽 꺾쇠 괄호(>)를 사용하여 명령의 출력을 리디렉션할 수 있습니다(일반적으로 파일로 리디렉션). 예를 들면 다음과 같습니다.
ls > files.txt
cat files.txt
wc doesntexist.txt 2> errors.txt
cat errors.txt
|: 파이프
“파이프”는 명령을 서로 연결합니다. 한 명령의 출력을 가져와 다음 명령의 입력으로 제공합니다. 파이프된 명령의 수(체인 길이)는 임의적입니다.
여기서 `cat` 명령을 사용하여 `words.txt` 파일의 내용을 `grep`에 전달합니다. `grep`은 대소문자 ‘C’를 포함하는 모든 줄을 추출합니다. 그런 다음 `grep`은 이 줄을 `sort`로 전달합니다. `sort`는 `-r`(역방향) 옵션을 사용하므로 정렬된 결과가 역순으로 나타납니다.
cat words.txt | grep [cC] | sort -r
!: 파이프라인 논리 NOT 및 기록 연산자
느낌표(!)는 논리적 NOT을 의미하는 논리 연산자입니다.
[ ! -d ./backup ] && mkdir ./backup
이 명령줄에는 두 가지 명령이 있습니다.
첫 번째 명령은 대괄호 안에 있는 텍스트입니다.
두 번째 명령은 이중 앰퍼샌드(&&) 뒤에 오는 텍스트입니다.
첫 번째 명령에는 논리 연산자 !가 있습니다. 대괄호는 테스트가 진행 중임을 나타냅니다. `-d` (디렉토리) 옵션은 `backup`이라는 디렉토리가 있는지 테스트합니다. 두 번째 명령은 디렉토리를 만듭니다.
이중 앰퍼샌드(&&)가 두 명령을 구분하므로, Bash는 첫 번째 명령이 성공한 경우에만 두 번째 명령을 실행합니다. 그러나 이는 우리가 원하는 것과 정반대입니다. “backup” 디렉토리에 대한 테스트가 성공하면 생성할 필요가 없습니다. 그리고 “backup” 디렉토리에 대한 테스트가 실패하면 두 번째 명령이 실행되지 않아 누