2010-07-05 5 views
2

첫 번째 zsh 완료 스크립트를 만들려고합니다.이 경우 netcfg 명령입니다.zsh filename globbling/substitution

나는 소리가 들릴 수도 있습니다. 나는 첫 번째 장애물에 고착했습니다. 면책 조항,이 작업을 어떻게 해야할지 압니다. 그러나 나는 이것을하기 위해 "ZSH WAY"를 찾습니다.

파일을/etc/networking에 나열해야하지만 디렉터리 구성 요소가 아닌 파일 만 나열해야하므로 다음을 수행합니다. 내가 원하는 무엇

echo $(ls /etc/network.d/*(.)) 

/etc/network.d/ethernet-dhcp /etc/network.d/wireless-wpa-config 

했다 :

ethernet-dhcp wireless-wpa-config 

그래서 나는 (내 naivity 변명) 시도 :

echo ${(s/*\/)$(ls /etc/network.d/*(.))} 

/etc/network.d/ethernet-dhcp /etc/network.d/wireless-wpa-config 

이 작동하지 않는 것 같다, 내가 확신이해야 배열로 분할하고 마지막 부분을 얻음으로써 이것을 수행하는 영리한 방법이 될 수 있습니다.하지만 제가 말했듯이, 저는 이것에 대해 완전한 멍청한 반응을 보입니다.

감사의 말을 전합니다.

답변

0

basename(1) 디렉토리 구성 요소를 제거하는 데 익숙합니다. 또한 echo /etc/network/*을 사용하면 외부 ls 프로그램을 실행하지 않고 파일 목록을 가져올 수 있습니다. (외부 프로그램을 실행하면 원하는만큼 완성이 늦어 질 수 있는데 basename에 대해 zsh-builtin을 찾지 못했지만 아무 것도 없다는 것을 의미하지는 않습니다.)

도움말 :

haig% for f in /etc/network/* ; do basename $f ; done 
if-down.d 
if-post-down.d 
if-pre-up.d 
if-up.d 
interfaces 
+2

'$ {param # pattern}'매개 변수 확장은 접두사를 제거하는 방법입니다. '$ {param % pattern}'을 사용하여 접미사를 제거하십시오. –

7

일반 주 : 파일 이름을 생성하는 LS를 사용할 필요가 없습니다. echo some*glob을 사용할 수도 있습니다. 그러나 가능하면 삽입 된 개행 문자를 보호하려는 경우에도 그다지 좋지 않습니다. 아래의 첫 번째 예제는 포함 된 개행을 보호하기 위해 어레이에 직접 glob됩니다. 두 번째 것은 printf을 사용하여 변수를 사용하지 않고 동일한 작업을 수행하는 NUL 종료 데이터를 생성합니다.

당신이 변수를 사용하고자하는 경우 쉽게 할 수 있습니다 : 당신은 또한 변수없이 그것을 할 수 있지만, 여분의 물건 개별 항목을 분리

typeset -a entries 
entries=(/etc/network.d/*(.)) # generate the list 
echo ${entries#/etc/network.d/} # strip the prefix from each one 

이다 추악한 조금 :

# From the inside, to the outside: 
# * glob the entries 
# * NUL terminate them into a single string 
# * split at NUL 
# * strip the prefix from each one 
echo ${${(0)"$(printf '%s\0' /etc/network.d/*(.))"}#/etc/network.d/} 

어쨌든 (위의 예에서 명령 대체와 같은) 서브 쉘을 사용하려는 경우 glob 확장의 일부가 아니기 위해 디렉토리에 cd을 그냥 추가하십시오. 디렉토리 이름을 반복하십시오.) :

echo ${(0)"$(cd /etc/network.d && printf '%s\0' *(.))"} 
제안들에 대한
+0

불쌍한 나는 +1을 주었다. 세 가지 좋은 옵션, 모두 내 것보다 낫다. :) – sarnold

1

감사 할 zsh을의 또 더 읽고 며칠 나중에 문제로 돌아오고, 나는 내가가 공유하고 싶습니다 매우 간결한 해결책을 가지고 생각하는 데 귀하의 이익.

echo $ {$ (print /etc/network.d/ * (.)) : t}

+0

프로세스 대체를 사용하는 것은 나쁜 생각입니다. 공백이 포함 된 파일 이름을 mangle합니다. 더 복잡하고 느립니다. 더 간단하고 강건하며 효율적인'echo /etc/network.d/ * (.: t)'(또는'echo'대신에 원하는 실제 명령)을 사용하지 않으시겠습니까? – Gilles

2

크리스 욘센의 대답은, 그러나 그것은이 특별한 경우에 작동하는 매우 간단한 해결책 언급하지 않는, zsh을에 대한 유용한 정보를 :이 t을 사용

echo /etc/network.d/*(:t) 

을 기록 수정 자글로브 한정자입니다.

+0

좋은 해결책이지만 파일 이름에 공백이 있으면 제대로 작동하지 않습니다. –

+0

@AntonK globbing 부분은 임의의 파일 이름으로 올바르게 작동합니다. 문제가있는 부분은'echo'뿐입니다. 실제 예에서,'echo'는 사용하지 않을 것입니다. 여러분은 파일을 처리하고자하는 명령에리스트를 전달할 것입니다. – Gilles