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
重要なビットは 2 つのpushd
s で、popd
2 つの連続した一致する 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"