깊은 푸시 스택을 확장하는 더 좋은 방법이 있습니까?

깊은 푸시 스택을 확장하는 더 좋은 방법이 있습니까?

Bash 스크립트에서 다음과 같은 일이 발생하는 상황이 가끔 발생합니다.

pushd /tmp
wget -q http://download.redis.io/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
pushd redis-stable
make
sudo make install
popd; popd

중요한 비트는 두 개의 pushds 이며 popd두 개의 연속 일치하는 s로 끝납니다. 마지막 문장은 항상 나를 귀찮게 합니다. 스택에서 임의의 수의 항목을 꺼내고 원래 디렉터리로 다시 전환하려는 의도를 표현하는 더 좋은 방법이 있어야 하는 것 같습니다.

popd +nBash 매뉴얼 페이지를 검색하고 및 매개 변수 -n의 변형을 시도했지만 그들이 하는 일은 제거뿐인 것 같습니다.하나의항목은 매번 스택에서 제거됩니다. 이것은 내가 원하는 것이 아닙니다. 항목 수에 관계없이 디렉터리 스택을 확장하여 이전 상태로 되돌리려고 합니다.

OLDPWD=$(pwd)어딘가에 저장한 패러다임으로 전환하지 않고 cd $OLDPWD결국 이 작업을 수행할 수 있는 더 좋은 방법이 있습니까 ?

답변1

스크립트에서 이 디렉터리를 사용하는 것은 위험 때문에 문제가 됩니다. popd원래 디렉터리로 돌아가지 않고, 같은 이름의 디렉터리로 돌아갑니다. 원래 디렉터리가 이동된 경우 스크립트는 중간에 위치를 전환합니다. 이것은 원격 위험처럼 보일 수 있지만 조만간 그런 일이 일어날 것입니다.~ 할 것이다이런 일이 발생하면 스크립트 사용자는 당신을 저주할 것입니다.

일시적으로 다른 디렉토리에서 실행하려는 경우 가장 좋은 방법은 서브셸에서 스크립트의 해당 부분을 실행하는 것입니다.

( set -e
  cd "${TMPDIR:-/tmp}"
  wget -q http://download.redis.io/redis-stable.tar.gz
  tar xzf redis-stable.tar.gz
  cd redis-stable
  make
  sudo make install
)

예를 들어 여기서는 필요하지 않지만 서브쉘이 적합하지 않은 유사한 상황에서 유용할 수 있는 대안을 보여 드리겠습니다. 예를 들어 일부 변수를 설정하고 사용하려는 경우 디렉토리에서 사용할 수 있습니다.

실제로 다른 디렉터리로 전환할 필요가 없거나 단일 명령 기간 동안에만 다른 디렉터리로 전환해야 할 수도 있습니다. GNU 도구를 사용하는 경우 tar및 둘 다 디렉터리로 전환하기 위한 인수를 make지원합니다 . -C스크립트에서 이 디렉터리를 생성한다는 점을 고려하면 원래 디렉터리와 달리 해당 위치가 이동되지 않을 것이라고 가정하는 것이 합리적입니다.

set -e
: "${TMPDIR:=/tmp}"
wget -q -O "$TMPDIR/redis-stable.tar.gz" http://download.redis.io/redis-stable.tar.gz
tar xzf redis-stable.tar.gz -C "$TMPDIR"
make -C "$TMPDIR/redis-stable"
sudo make -C "$TMPDIR/redis-stable" install

다른 디렉터리로 전환하는 옵션이 없는 명령의 경우 더 좁은 하위 셸을 사용할 수 있습니다.

set -e
: "${TMPDIR:=/tmp}"
( cd "$TMPDIR"
  wget -q http://download.redis.io/redis-stable.tar.gz
  tar xzf redis-stable.tar.gz -C "$TMPDIR"
)
( cd "$TMPDIR/redis-stable"
  make
  sudo make install
)

앞뒤로 전환해야 하는 경우 여러 호출에 비해 확실한 개선점은 돌아가고 싶지 popd않은 디렉터리에 전화하는 대신 돌아가고 싶을 때 전화하는 것입니다.cdcdpushd

set -e
pushd "${TMPDIR:-/tmp}"
wget -q http://download.redis.io/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
cd redis-stable
make
sudo make install
popd

pushd그러나 나는 and 를 전혀 사용하지 않는 것을 권장합니다 popd. 이는 대화형 사용을 위해 설계되었으며 스크립트에서는 무엇보다 혼란스러운 경향이 있습니다. 현재 디렉터리의 위치를 ​​저장하려면 변수에 저장하세요. 이렇게 하면 스크립트를 더 쉽게 읽을 수 있으므로 독자는 popd호출이 어디로 돌아갈지 알아낼 필요가 없습니다 .

set -e
original_directory="$PWD"
cd "${TMPDIR:-/tmp}"
wget -q http://download.redis.io/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
cd redis-stable
make
sudo make install
cd "$original_directory"

답변2

팝하려는 디렉토리 스택의 레벨에 대한 정신적 이미지가 있는 경우 다음 함수를 사용할 수 있습니다.

function mpopd {
  n=$1
  while [[ $n > 0 ]]
  do
    popd
    n=$((n-1))
  done
}

실행 예시:

[schaller@host smitelli] dirs
~/tmp/smitelli
[schaller@host smitelli] pushd tmp/
~/tmp/smitelli/tmp ~/tmp/smitelli
[schaller@host tmp] pushd redis-stable/
~/tmp/smitelli/tmp/redis-stable ~/tmp/smitelli/tmp ~/tmp/smitelli
[schaller@host redis-stable] mpopd 2
~/tmp/smitelli/tmp ~/tmp/smitelli
~/tmp/smitelli

답변3

작업을 시작하기 전에 새 하위 쉘을 시작한 다음 완료되면 종료하고 원래 쉘과 디렉토리로 돌아갈 수 있습니다.

pushd그러나 나중에 동일한 작업을 반복해야 하는 경우가 많으 므로 디렉터리 기록을 보관하는 것이 좋습니다 . 실제로 cd해당 항목의 별칭을 지정한 pushd다음 다른 기능을 사용하여 아무것도 잃지 않고 디렉터리 스택을 쉽게 탐색할 수 있습니다. 대신 디렉터리 스택을 나열하고 어떤 기능으로 이동할지 묻는 것과 같은 간단한 작업을 수행할 수 있습니다.

cdp(){
  select v in $(dirs -l -p)
  do pushd "$v"
     break
  done
}

관련 정보