2012-07-25 7 views
21

echo $VARIABLE 명령에서 얻은 경로 목록을 반복하고 싶습니다. 예를 들어Bash에서 경로 변수의 요소를 반복합니다.

:

echo $MANPATH

/usr/lib:/usr/sfw/lib:/usr/info

를 반환 그래서 그 세 개의 다른 경로, 콜론로 구분된다. 나는 각각의 경로를 반복하고 싶다. 그렇게 할 수있는 방법이 있습니까? 감사.

지금까지 모든 답장을 보내 주셔서 감사합니다. 실제로 실제로 루프가 필요없는 것 같습니다. 콜론을 꺼내는 방법이 필요하므로이 세 경로에서 하나의 ls 명령을 실행할 수 있습니다.

답변

15

Bash의 패턴 대체 parameter expansion을 사용하여 루프 변수를 채울 수 있습니다. 예 :

MANPATH=/usr/lib:/usr/sfw/lib:/usr/info 

# Replace colons with spaces to create list. 
for path in ${MANPATH//:/ }; do 
    echo "$path" 
done 

참고 : 대체 확장을 따옴표로 묶지 마십시오. MANPATH에서 확장 된 값을 단일 루프가 아닌 for-loop로 분리 된 단어로 해석하려고합니다.

+5

공백이 있으면 어떨까요? –

+7

$ PATH가 공백이 아닌 구분자를 사용하는 이유는 정확하게 부분 문자열에 공백이 포함되어있는 경우에 가장 잘 이해할 수 있습니다. @ choroba의 대답은이 점에있어서 정확합니다. – intelfx

+1

@intelfx : 질문에 [tag : linux]라는 태그가 붙어 있습니다. Linux에서 * MANPATH *에 공백이 있으면 Linux를 잘못 처리하고있는 것입니다. Q.E.D. –

0

당신은이를 위해 $ {} 표기법으로 X에 대한 배쉬의를 사용할 수 있습니다

for p in ${PATH//:/$'\n'} ; do 
    echo $p; 
done 
+3

공백을 처리하지 않습니다. – codeforester

39

할 수 있습니다 내부 필드 구분자 설정 : 내가 IFS의 변화 때문에 서브 쉘을 사용

(IFS=: 
    for p in $MANPATH; do 
     echo "$p" 
    done 
) 

내 현재 쉘에 반영되지 않습니다.

IFS=: read -r -d '' -a path_array < <(printf '%s:\0' "$MANPATH") 

이 유일한 강력한 솔루션입니다 : 정확히 당신이 원하는 것을 할 것입니다 :에 문자열을 분할

+6

$ MANPATH에 공백이 포함되어 있어도 이것이 작동한다고 생각합니다. – user1277476

+3

예! 공백이있는 경로 (또는 IFS가 시스템에있는 경로)와 일관되게 작동하는 유일한 대답입니다. Cygwin, Fedora, Ubuntu에서 테스트되었고 $ PATH에 나를 위해 workd되었습니다. – hobs

+1

공간을 잘 처리하지만 glob 문자는 처리하지 않습니다. – codeforester

0
for p in $(echo $MANPATH | tr ":" " ") ;do 
    echo $p 
done 
+1

-1, 바람직하지 않은'echo'와 치환이 쉘에 의해 수행 될 수있을 때의 서브 프로세스. – tripleee

+2

따옴표가 필요하지만 쉘 내장의 라인 노이즈보다 훨씬 더 읽기 쉽습니다. 조개 껍질은 적이 아닙니다. – user1277476

+0

따옴표를 붙이면 해결할 수 없으며 적어도 @tripleee가 언급하지 않은 다른 문제가 하나 있습니다. [왜 printf가 echo보다 나은가요?] (https://unix.stackexchange.com/q/65803)를보십시오. 그러나 현재의 매우 낮은 점수는 받아 들여지는 "해결책"보다 기능적으로별로 나쁘지 않기 때문에 가혹한 것처럼 보입니다. – pjh

9

배쉬에서이 작업을 수행하는 표준 방법은 적절하게 read 내장을 사용하는 것입니다 구분 문자 :이고 공백, 개행 문자 및 *, [ ] 등과 같은 glob 문자는 안전합니다 (다른 답변과 달리 모두 깨졌습니다). $IFS이 유지됩니다 동안 안전하게 하나의 루프로 $PATH 통해 갈 수있는이 방법으로

for p in "${path_array[@]}"; do 
    printf '%s\n' "$p" 
done 
2

:이 명령 후

, 당신은 배열 path_array을해야합니다, 당신은 그것을에 루프 수 루프의 내부 또는 외부와 동일합니다.

while IFS=: read -d: -r path; do # `$IFS` is only set for the `read` command 
    echo $path 
done <<< "${PATH:+"${PATH}:"}" # append an extra ':' if `$PATH` is set 

당신은 $IFS의 값을 확인할 수

IFS='xxxxxxxx' 
while IFS=: read -d: -r path; do 
    echo "${IFS}${path}" 
done <<< "${PATH:+"${PATH}:"}" 

출력은 다음과 같이 될 것입니다.

xxxxxxxx/usr/local/bin 
xxxxxxxx/usr/bin 
xxxxxxxx/bin 

another question on StackExchange을 참조하십시오.

0
IFS=: 
arr=(${MANPATH}) 
for path in "${arr[@]}" ; do # <- quotes required 
    echo $path 
done 

... 그것은 공간의 관리 가지고 간다 : O를)하지만이 같은 경우도 빈 요소를 추가합니다 '(

:/usr/bin::/usr/lib: 

가 ... 다음 인덱스 0,2가 비어을

python -c "import os,sys;[os.system(' '.join(sys.argv[1:]).format(p)) for p in os.getenv('PATH').split(':')]" echo {} 

또는 같은 : 인덱스 4 명령 행에서, 이것은 또한 파이썬으로 해결 될 수있는 모든

+0

이것은 glob 문자를 처리하지 않습니다. – pjh

0

설정 밤은 왜 '), 말할 수 없다 별명 사용 예와

alias foreachpath="python -c \"import os,sys;[os.system(' '.join(sys.argv[1:]).format(p)) for p in os.getenv('PATH').split(':')]\"" 

는 :

foreachpath echo {} 

이 방법의 장점은 {} 연속으로 각 경로에 의해 대체되어야한다는 것이다. 예를 들어, 디렉토리에있는 모든 파일 및 디렉토리의 크기를 $PATH에 나열하는 등 모든 종류의 명령을 생성하는 데 사용할 수 있습니다. 이름에 공백이있는 디렉토리를 포함 : 여기

foreachpath 'for e in "{}"/*; do du -h "$e"; done' 

것은 $HOME/.allbin$PATH에있는 모든 파일 및 디렉토리에 대한 심볼릭 링크를 생성하여 $PATH 변수의 길이를 단축 한 예이다. ... 이것은 일상적인 사용에 대한 유용한 아니라, bitbake 명령 줄의 일부로서 전체 $PATH를 사용하기 때문에 당신이하는 docker 용기에 too many arguments 오류 메시지가있는 경우 유용 할 수 있습니다

mkdir -p "$HOME/.allbin" 
python -c "import os,sys;[os.system(' '.join(sys.argv[1:]).format(p)) for p in os.getenv('PATH').split(':')]" 'for e in "{}"/*; do ln -sf "$e" "$HOME/.allbin/$(basename $e)"; done' 
export PATH="$HOME/.allbin" 

이해야 또한 이론적으로는 실행되는 모든 명령을 검색 할 경로가 적기 때문에 일반 셸 사용과 셸 스크립트의 속도를 높입니다. 그것 꽤 해키지만, 나는 그렇게하지 않는 것이 좋습니다. 누구나$PATH 이렇게 짧게하는 것이 좋습니다.

foreachpath 별칭이 유용 할 수 있습니다.

관련 문제