루프 변수의 출력이 예상과 다른 값을 표시합니다.

루프 변수의 출력이 예상과 다른 값을 표시합니다.

back/현재 작업 디렉토리에 와 이라는 두 개의 폴더가 있다고 가정해 보세요 front/. 나는 그들 각각의 내부로 들어가서 몇 가지 일을 하려고 노력하고 있습니다. 아래의 간단한 스크립트에서:

for dir in */ ; do
    echo "$(dir)"
done

나는 다음과 같은 결과를 기대했습니다.

back
front

그러나 내가 얻는 것은 다음과 같습니다.

back  front
back  front

모르겠어요. 결과는 cd폴더에 들어가려고 하면 다음과 같습니다 .

for dir in */ ; do
    echo "$(dir)"
    cd $(dir)
    echo "$(pwd)"
    cd ..
done

나는 얻다:

back  front
/path/to/back
back  front
/path/to/back

즉, 나는 절대 들어가지 않습니다 front/. 누군가 내가 뭘 잘못하고 있는지 이해하도록 도와줄 수 있나요?

답변1

POSIX와 유사한 쉘에서 $(cmd)다음 구문은 다음과 같습니다.명령 대체, 후행 개행 문자를 뺀 $(cmd)출력으로 확장됩니다 .cmd

대신 당신이 원하는 것은매개변수 확장: $dir또는 ${dir}(여기서는 매개변수가dir 변하기 쉬운).

pwd( print working irectory)는 현재 작업 디렉토리에 대한 경로를 포함하는 1 특수 변수 d의 내용을 출력하는 명령이므로 개행 문자로 끝나지 않는 한 동일한 것으로 확장됩니다 .$PWD$(pwd)$PWD$PWD

그래서 당신은 원합니다:

for dir in */; do 
  (
    printf '%s\n' "$dir"
    cd -- "$dir" &&
      printf '%s\n' "$PWD"
  )
done

또는:

for dir in */; do 
  (
    printf '%s\n' "$dir"
    cd -- "$dir" &&
      pwd
  )
done

또한 그것을 기억하십시오

  • echo임의의 데이터를 출력하는 데 사용할 수 없습니다. printf대신 사용하세요.
  • 일반적으로 명령의 종료 상태를 확인해야 합니다. 여기서 출력을 확인하지 않으면 첫 번째 실패 시 다음이 잘못된 위치에 놓이게 된다는 cd의미입니다 .cd ..cd
  • 후자를 사용하는 것보다 cd서브셸에서 실행하는 것이 더 좋습니다 (사용하여) . 후자는 항상 초기 위치로 돌아가는 것을 보장하지 않습니다(관련된 심볼릭 링크가 있거나 일부 경로 구성 요소의 이름이 간격에서 변경된 경우).(...)cd ..
  • --옵션이 아닌 항목이 시작되지 않는다고 보장할 수 없는 경우 -(또는 +일부 명령의 경우에도 문제가 될 수 있는 경우) 옵션과 옵션이 아닌 옵션을 구분하는 데 사용해야 합니다.
  • POSIX와 유사한 쉘에서 매개변수 확장 및 명령 대체(및 산술 확장)는 일반적으로 원하지 않는 암시적 분할+glob(zsh 제외)을 거치므로 인용되어야 합니다.

또한 bash(및 zsh를 제외한 다른 POSIX 셸)에서 glob이 어떤 파일과도 일치하지 않으면 확장되지 않은 상태로 남아 있다는 점에 유의하세요.

따라서 현재 작업 디렉터리에 다음 유형으로 판단할 수 있는 숨김 파일이 아닌 파일이 포함되어 있지 않은 경우예배 규칙서, glob 패턴은 빈 목록 대신 */자체적으로 확장되며 해당 디렉터리에 들어갈 수 없다는 오류가 표시될 가능성이 높습니다 .*/cd*/

에서는 in 과 같이 glob 한정자를 zsh사용합니다 (또는 로 끝나지 않도록 ).Nfor dir in */(N); do...for dir in *(N-/); do...$dir/

ksh93에서: for dir in ~(N)*/; do....

에서는 일시적으로 전역적으로 옵션을 bash설정할 수 있습니다 .nullglob

shopt -s nullglob
for dir in */; do
  ...
done
shopt -u nullglob

완전성을 위해 $(var)다음과 같은 구문이 사용됩니다.매크로Makefile명령 에서 사용되는 s 의 확장입니다 make.

awk언어 에서는 $필드를 역참조하는 단항 연산자이며 변수 var를 참조하는 데만 사용됩니다 awk. 따라서 or $(var)와 동일 하고 번째 필드(또는 0인 경우 전체 레코드 ) 로 확장됩니다 .$var$ varvarvar

rc유사한 쉘 에서는 , , $(var)와 동일하게 작동합니다 . 이는 에 전달된 한 요소의 목록 이므로 일반적으로 just를 사용하지만 변수를 역참조하게 됩니다 .$var$ var$ 'var'$ ( 'var' )$var$var

TCL에서는 $(var)키 이름이 비어 있는 배열 변수의 값으로 확장됩니다 var.

$ tclsh
% array set {} {foo 1 bar 2}
% puts $(foo)
1

¹ 그렇습니다. 이 맥락에서는 P린트 P가 별로 의미가 없습니다. 추측할 수 있듯이 pwd명령(70년대 중반 Unix V5에서)이 처음 $PWD이었고논리적POSIX에 의해 지정된 현재 작업 디렉토리의 처리는 나중에 나왔습니다(80년대 초반 ksh에서 실제로는 (누락 및 따옴표가 있습니다!) pwd의 별칭이었고 문서에서는 resent orking irectory라는 약어로 표기되었습니다 ). 동일한 목적을 위한 ( 현재 orking irectory) 변수가 있습니다.print - $PWD-r$PWDPWDtcsh$cwdcwd

관련 정보