서브 쉘을 사용하지 않고 명령 대체를 요구하는 시나리오가 있습니다. 나는 이와 같은 구조를 가지고있다 :
pushd $(mktemp -d)
이제 임시 디렉토리를 종료하고 한 번에 제거하고 싶습니다.
rmdir $(popd)
그러나 popd
팝 된 디렉토리를 반환하지 않고 (현재 새로운 디렉토리를 반환) 하위 쉘에서 수행되기 때문에 작동 하지 않습니다.
같은 것
dirs -l -1 ; popd &> /dev/null
팝 된 디렉토리를 반환하지만 다음과 같이 사용할 수 없습니다 :
rmdir $(dirs -l -1 ; popd &> /dev/null)
popd
서브 쉘에만 영향을 미치기 때문 입니다. 요구되는 것은 이것을 할 수있는 능력이다 :
rmdir { dirs -l -1 ; popd &> /dev/null; }
그러나 그것은 잘못된 구문입니다. 이 효과를 얻을 수 있습니까?
(참고 : 임시 디렉토리를 변수에 저장할 수 있다는 것을 알고 있습니다. 필요하지 않고 프로세스에서 새로운 것을 배우려고했습니다!)
답변
질문 제목을 선택하는 것은 약간 혼란 스럽습니다.
pushd
/ popd
하는 csh
기능에 의해 복사 bash
하고 zsh
, 기억 디렉토리의 스택을 관리하는 방법입니다.
pushd /some/dir
푸시 현재 스택 상 작업 디렉토리, 그리고 다음 인쇄합니다 후 현재 디렉토리를 변경하는 (그리고 /some/dir
그 스택의 콘텐츠 하였다 () 공간으로 구분.
popd
스택의 내용을 다시 인쇄하고 (격리 된 공간) 스택의 맨 위 요소로 변경하여 스택에서 튀어 나옵니다.
(또한 일부 디렉토리는 해당 디렉토리 ~/x
또는 ~user/x
표기법 으로 표시 될 것입니다 ).
스택은 현재 보유하고 경우에 따라서 /a
하고 /b
, 현재 디렉토리는 /here
당신이 실행중인 :
pushd /tmp/whatever
popd
pushd
인쇄 할 /tmp/whatever /here /a /b
과 popd
의지 출력을 /here /a /b
하지 /tmp/whatever
. 그것은 명령 대체를 사용하는 것과 무관합니다. popd
이전 디렉토리의 경로를 얻는 데 사용할 수 없으며 일반적으로 출력을 포스트 처리 할 수 없습니다 ( 해당 디렉토리 스택의 요소에 액세스하려면 일부 쉘의 배열 $dirstack
또는 $DIRSTACK
배열 참조 )
어쩌면 당신은 원할 것입니다 :
pushd "$(mktemp -d)" &&
popd &&
rmdir "$OLDPWD"
또는
cd "$(mktemp -d)" &&
cd - &&
rmdir "$OLDPWD"
그래도 사용합니다 :
tmpdir=$(mktemp -d) || exit
(
cd "$tmpdir" || exit # in a subshell
# do what you have to do in that tmpdir
)
rmdir "$tmpdir"
어쨌든 서브 쉘에서 pushd "$(mktemp -d)"
실행되지 않습니다 pushd
. 그렇다면 작업 디렉토리를 변경할 수 없습니다. 그것이 mktemp
서브 쉘에서 실행됩니다. 별도의 명령이므로 별도의 프로세스에서 실행해야합니다. 파이프에 출력을 기록하고 쉘 프로세스는 파이프의 다른 쪽 끝에서 출력을 읽습니다.
ksh93은 명령이 내장되어있을 때 별도의 프로세스를 피할 수 있지만, 여전히 포킹으로 제공되는 별도의 환경에 의존하기보다는 서브 쉘 (다른 작업 환경)이 에뮬레이트됩니다. 예를 들어,에 ksh93
, a=0; echo "$(a=1; echo test)"; echo "$a"
어떤 포크는 아직 포함되지되지만 echo "$a"
출력 0
.
당신의 출력을 저장하려면 여기, mktemp
당신이 그것을 통과 동시에 변수에, pushd
로를 zsh
, 당신은 할 수 있습니다 :
pushd ${tmpdir::="$(mktemp -d)"}
다른 Bourne과 같은 껍질 :
unset tmpdir
pushd "${tmpdir=$(mktemp -d)}"
또는 $(mktemp -d)
변수에 명시 적으로 저장하지 않고 여러 번 출력을 사용하려면 zsh
익명 함수를 사용할 수 있습니다 .
(){pushd ${1?} && cd - && rmdir $1} "$(mktemp -d)"
답변
디렉토리를 떠나기 전에 먼저 링크를 해제 할 수 있습니다.
rmdir "$(pwd -P)" && popd
또는
rmdir "$(pwd -P)" && cd .. # yes, .. is still usable
하지만 참고 pushd
및 popd
되지 스크립트에 대한 대화 형 쉘 도구는 정말 (그들이 그렇게 수다스러운 이유의 것을 그들은 성공할 때 실제 스크립트 명령이 침묵).
답변
bash dirs
에서 pushd / popd 메소드로 기억 된 디렉토리 목록을 제공하십시오.
또한 dirs -1
목록에 포함 된 마지막 디렉토리를 인쇄합니다.
따라서를 실행하여 이전에 만든 디렉토리를 제거 pushd $(mktmp -d)
하려면 다음을 사용하십시오.
rmdir $(dirs -1)
그런 다음 popd
목록에서 이미 제거 된 디렉토리 :
popd > /dev/null
한 줄에 모두 :
rmdir $(dirs -1); popd > /dev/null
~/x
또는 ~user/x
표기법 을 피하기 위해 옵션 (-l)을 추가하십시오 .
rmdir $(dirs -l -1); popd > /dev/null
요청한 라인과 매우 유사합니다.
를 사용 &>
하여 오류보고를 숨길 수 있다는 점을 제외하고 popd
.
주 : 디렉토리 후 남아 rmdir
는 그대로 pwd
그 시점에서. 그리고 popd
명령 후에 실제로 연결이 해제됩니다 (남은 링크는 사용되지 않음).
변수 “OLDPWD”를 지원하는 쉘 (대부분의 본과 같은 쉘 : ksh, bash, zsh have $OLDPWD
) 에 사용할 수있는 옵션이 있습니다 . 그 흥미 롭다 DIRS, 포드, PUSHD 기본적으로 구현하지 않습니다 KSH (사용할 수 있으므로, 여기에 사용할 수 없습니다 또한 popd 명령이없는 lksh, 대시 등을) :
popd && rmdir "$OLDPWD"
또는 더 관용적 인 (위와 같은 쉘 목록) :
popd && rmdir ~-