다소 복잡한 alias 를 만들었는데, 따옴표를 넣어야 하는 상황이라 오류가 발생했다.
넣으려는 명령은 이랬다.
updl=$(sudo opkg list-upgradable | cut -f 1 -d ' ') ; if [[ $(wc -l <<< $updl) > 1 ]] ; then xargs sudo opkg upgrade <<< "$updl" ; else echo '지금은 없네요' ; fi"
Openwrt opkg 에서 판올림을 하는 명령을 살짝 변형해봤다.
판올림이 가능한 지 먼저 확인하고, 가능한 꾸러미가 있으면( wc -l
로 확인) 판올림을 수행하고, 없다면 “없네요”를 출력하고 끝낸다. 명령어로 넣으면 그냥 간단한데..
이걸 Alias 에 넣으려니 오작동이 생겨나버렸다.
alias="updl=$(sudo opkg list-upgradable | cut -f 1 -d ' ') ; if [[ $(wc -l <<< $updl) > 1 ]] ; then xargs sudo opkg upgrade <<< "$updl" ; else echo '지금은 없네요' ; fi"
Shell 을 띄우면(즉, 터미널을 열면) 아무 반응이 없거나, 갑자기 password 를 물어보거나 등등 바로 프롬프트가 떨어지질 않았다.
뭔가 문제가 있긴 한건데.. 과연 어디서 잘못한 걸까? 답은 ‘이스케이프’였는데, 특이하게도 $ 에도 해줘야 한다는 사실!
이게 답이다.
alias upg="updl=\$(sudo opkg list-upgradable | cut -f 1 -d ' ') ; if [[ \$(wc -l <<< \$updl) > 1 ]] ; then xargs sudo opkg upgrade <<< \"\$updl\" ; else echo '지금은 없네요' ; fi"
겹따옴표로 감쌌을 경우, 안에 있는 홑따옴표는 그냥 쓰면 된다. 즉, 이스케이핑을 할 필요가 없다. 괄호/대괄호도 그냥 쓴다. 겹따옴표는 당연히 이스케이핑 해야 하며, $도 마찬가지.
Bash 에서도 마찬가지겠지만, 적어도 Zsh 에서는 위 방법이 정답이었다.
지식의 보고 Stack overflow 에게 감사를.
참고로, 위 명령이 간단해보이지만, 내 리눅스 10년 내공이 만들어냈다고 해도 과언이 아니다. 좀 더 간단명료한 방법도 틀림없이 있겠지만.. 내가 지금 생각할 수 있는 방법은 저게 최선이다.
먼저, list-upgradable 이 0 보다 클 경우에만 작업을 하기 위해 if 가 필요했다. 그 내용은 여기서 참고했다. 사실 cut 을 여기서 할 필요는 없는데..
wc -l <<< $updl
은 Here String 문법이다. 열심히 공부하고 정리해놓은 보람이 있네. (이 말 한마디 하고 싶어서 추가로 이 내용을 쓰게 됐네. 허허허)
사실, 저 방식대로 한다면 Here String 을 모르고는 진행이 어렵다. 파이프라인 만으로는 아마 구현이 어렵지 않을까 싶은데.. 그 근거로는 $(…) 로 처리되는 서브셸로 파이프라인이 잘 넘어갈까?? 라는 의문을 들 수 있다. 내가 시험해본 바로는, 넘어가질 않는다.)
xargs 뒤에도 역시 Here String 이 쓰였다. 처음엔 그냥 xargs 없이 sudo opkg upgrade <<< $updl
로만 작성했는데, 원하는대로 작동되지 않았다. man page 를 보니 이렇게 나와있다.
The specified command will be invoked as many times as necessary to use up the list of input items.
xargs 는, 인수(여기서는 $updl)가 목록으로 되어 있을 경우, 명령어(opkg upgrade)를 알아서 자동으로 그 숫자만큼 재실행되게끔 해주는 역할을 하는 모양이다.
간단하게 말해서 for loop 를 돌려주는 프로그램이라 생각하면 되겠다.
** 지금까진 그저 xargs 는 Pipeline 을 사용할 때는 그냥 써야만 하는 프로그램으로 생각했었다. 다시 말해서, 별 관심이 없었다.
좀 더 멋진 방법은 없으려나??