サブシェルを使用せずにコマンド置換が必要なシナリオがあります。私は次の構造を持っています:
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; }
しかし、これは間違った構文です。そのような効果を得ることができますか?
(注:一時ディレクトリを変数に保存できることを知っています。
ベストアンサー1
あなたの質問のタイトルの選択は少し混乱しています。
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 -v tmpdir
pushd "${tmpdir=$(mktemp -d)}"
あるいは、出力を$(mktemp -d)
変数に明示的に保存せずに複数回使用する場合は、zsh
匿名関数を使用できます。
(){pushd ${1?} && cd - && rmdir $1} "$(mktemp -d)"