셸의 느낌표는 외침이 아니다: 반복 입력을 줄이는 ! 활용법
요약
Bash의 '!' 치환 문법이 가진 위험성과 한계를 분석하고, fish shell이나 zsh의 편리한 기능 및 readline 기반의 단축키 활용법을 소개합니다. 명령줄 인터페이스를 더 효율적이고 안전하게 사용하는 팁을 다룹니다.
핵심 포인트
- Bash의 '!' 문법은 실행 전 확장 결과를 확인하기 어려워 위험할 수 있음
- fish shell은 사용자 친화적인 자동 완성 및 편리한 치환 문법을 제공함
- readline 기반 환경에서 Ctrl-O를 활용해 명령 기록을 순환하며 실행 가능
- zsh의 탭 확장을 이용하면 이벤트 지정자를 안전하게 미리 볼 수 있음
- 명령어를 빠르게 찾는 것보다 직접 편집하여 의도를 확인하는 것이 더 안전함
POSIX 지옥에 갈지도 모르지만 fish shell을 쓰면 이런 번거로움을 신경 쓰지 않아도 됨. 자동 완성이 자연스럽게 잘 돼서 당연하게 여기고 있음
bash나 zsh 대신 fish·nushell처럼 사용자 친화적인 대안을 쓰지 않는 사람이 많다는 게 놀라움
기본 셸을 고수하는 이유는 대개 두 가지임. 레거시 시스템에 (ba)sh만 있고 관리자 권한도 없어서 익숙한 셸을 계속 쓰는 경우는 이해할 만함. 나도 기관의 컴퓨팅 클러스터에 자주 SSH로 접속하지만 fish 바이너리를 내려받거나 빌드한 뒤 .bashrc에 한 줄 추가해 해결했으며, 물론 항상 가능한 방법은 아님
다른 부류는 명령줄 인터페이스 자체를 두려워하고 bash가 무엇인지도 잘 모른 채 ChatGPT로 모든 걸 해결하며 더 깊이 배우려 하지 않음. 아쉽지만 이런 걸 배우는 과정을 즐기는 내가 특이한 쪽일 수 있음
Linux에서 PowerShell을 쓰는 드문 사람 중 하나로서 공감함. bash 특유의 이상한 동작을 상당수 피할 수 있어 편리함
fish가 이런 치환 문법을 받아들이도록 직접 수정했으며, 이제는 없으면 쓰기 매우 어려움
fish에는 앞서 소개된 기능 상당수와 대응하는 키 바인딩도 있음. Alt-E로 명령줄을 편집기에서 열고 Alt-Up으로 직전 명령의 마지막 인수를 가져올 수 있음
일종의 편법이지만 최근 Bash를 비롯한 readline 기반 환경의 Ctrl-O 를 알게 됨 Ctrl-R 등으로 이전 명령을 불러온 뒤 Ctrl-O를 누르면 그 명령을 실행하고 기록의 다음 명령으로 이동함
Ctrl-O를 아주 좋아함. vim some.config와 run-something처럼 두세 명령을 번갈아 실행한다면 각각 한 번만 입력한 뒤 Alt-2 또는 Alt-3, 위쪽 화살표, Ctrl-O만 계속 사용할 수 있음
기록의 마지막 명령에서 Ctrl-O를 누르면 묶음의 첫 명령으로 돌아감. 도중에 다른 명령을 실행하거나 수정하면 순환할 명령들을 다시 기록 맨 아래로 불러와 설정해야 해서 실용성은 애매하지만 그래도 즐겨 사용함
!의 문제는 아는 한 실행 전에 확장 결과를 볼 수 없다는 것임
Bash 설명서의 history-expand-line (M-^) 이 원하는 기능과 비슷해 보임. 1990년대에도 이 기능을 알았다면 기록 확장을 완전히 위험한 기능으로 여기지 않았을지도 모름
그래도 !를 발견하지 못하거나 결과 확인을 위해 M-^를 누르는 걸 잊으면 예상치 못한 결과가 생길 가능성이 큼
history-expand-line (M-^)
Perform history expansion on the current line. See HISTORY EXPANSION below for a description of history expansion.
zsh는 이벤트 지정자에 대한 탭 확장을 어느 정도 지원함. <tab>을 누르면 !:$는 ~/some/path로, !z는 가장 최근의 가까운 일치 항목인 zsh --version으로 명령줄에서 확장됨
$ zsh --version
zsh 5.9 (arm64-apple-darwin25.0)
$ ls ~/some/path
ls: /some/path: No such file or directory
$ mkdir !:$ #<tab> will expand to ~/some/path in the readline
$ !z #<tab> again will expand to the most recent closest-match, i.e. 'zsh --version'
대부분의 상황, 특히 셸 명령 상당수처럼 파괴적일 수 있는 작업에서는 이전 줄을 빠르게 찾아 직접 편집하는 편이 훨씬 나음
최근 아래 find 명령들의 함정에 당했음. 문제를 모르면서 find를 쓴다면 꼭 알아볼 필요가 있음
!find로 직전 호출을 가져왔다면 이런 문제가 훨씬 심각했을 것임. 명령줄을 직접 편집하면 의도와 다르다는 사실을 발견할 가능성이 커짐
이전 명령을 빠르게 찾고 수정할 때는 현재 atuin을 쓰지만, 단순한 Ctrl-R이나 위·아래 화살표도 좋은 방법임. zsh에서는 <tab>으로 미리 확장해 Enter를 누르기 전에 실행할 내용을 확인할 수 있음
이 느낌표 확장 기능을 끄고 싶음. 커밋 메시지에 !를 넣었다가 우연히 발동한 경우밖에 없었음 "..." 대신 '...'를 써야 한다는 건 알지만 습관을 바꾸기 어려움. 잘못된 ! 때문에 셸이 명령을 너무 일찍 거부하면 기록에도 남지 않아 위쪽 화살표로 불러와 고칠 수도 없어 매우 성가심
기록 확장은 의도적으로 써도 결과를 예측하기 어렵고, 실수로 발동하면 무엇이 잘못됐는지 파악하기도 힘든 거대한 발밑의 총이라고 판단함
거의 30년 동안 .bashrc에 set +o histexpand를 넣어 사용해 왔음. 대신 가끔 M-.으로 직전 명령의 마지막 인수를 삽입하지만, 대개는 마우스로 복사해 붙여 넣음
기록 확장은 bash가 csh에서 가져온 기능이며, 이 때문에 csh 프로그래밍뿐 아니라 csh 자체도 해로운 것으로 간주해야 한다는 생각이 들었음
예전에는 이런 기능을 썼지만 확장 결과를 미리 보지 못해 여러 번 피해를 본 뒤 fish로 옮겼음. 명령 기록 기반 자동 완성이 자동으로 동작해 훨씬 쉽고 오류 가능성도 낮음
AI 자동 생성 콘텐츠
본 콘텐츠는 GeekNews의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기