![깊은 푸시 스택을 확장하는 더 좋은 방법이 있습니까?](https://linux55.com/image/91975/%EA%B9%8A%EC%9D%80%20%ED%91%B8%EC%8B%9C%20%EC%8A%A4%ED%83%9D%EC%9D%84%20%ED%99%95%EC%9E%A5%ED%95%98%EB%8A%94%20%EB%8D%94%20%EC%A2%8B%EC%9D%80%20%EB%B0%A9%EB%B2%95%EC%9D%B4%20%EC%9E%88%EC%8A%B5%EB%8B%88%EA%B9%8C%3F.png)
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
중요한 비트는 두 개의 pushd
s 이며 popd
두 개의 연속 일치하는 s로 끝납니다. 마지막 문장은 항상 나를 귀찮게 합니다. 스택에서 임의의 수의 항목을 꺼내고 원래 디렉터리로 다시 전환하려는 의도를 표현하는 더 좋은 방법이 있어야 하는 것 같습니다.
popd +n
Bash 매뉴얼 페이지를 검색하고 및 매개 변수 -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
않은 디렉터리에 전화하는 대신 돌아가고 싶을 때 전화하는 것입니다.cd
cd
pushd
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
}