一連のディレクトリを一度にプッシュする方法は?

一連のディレクトリを一度にプッシュする方法は?

foo私はサブディレクトリを含むディレクトリにあり、bar1 bar2それがbar3すべてです。

pushd、およびをfoo1つのコマンドで実行したいのですが、停止しました。bar1bar2bar3

find `pwd` | xargs pushd

返品

xargs: pushd: No such file or directory

この問題を回避するためにwhileループを使用してみました。

find `pwd` | while read line ; do pushd $line ; done

これにより、正しく表示される出力が提供されます。

~/foo ~/foo
~/foo/bar1 ~/foo ~/foo
~/foo/bar2 ~/foo/bar1 ~/foo ~/foo
~/foo/bar3 ~/foo/bar2 ~/foo/bar1 ~/foo ~/foo

しかし、後でこれを使用すると、スタックdirsに新しいディレクトリを追加していないことがわかります。

~/foo

何が間違っているのかを理解できる人はいますか?

ベストアンサー1

あなたは非常に近いです。欲しいことができます

while read line; do pushd "$line"; done < <(find "$(pwd)" -type d)

コマンドの問題は、有用な場合は基本(親)プロセスでpushd実行するcd必要があり(システムの設定方法によって若干の違いがある)、パイプラインのコマンドが子プロセス(子プロセス)で実行されることです。 )。パイプを与えずに魔法のようにパイプを与えます。< <(cmd)

POSIXは 。<(cmd)

残念ながら、このxargsアプローチは失敗する運命です。なぜならpushd(like cd)はシェル組み込み(つまり、プログラムpushd)と呼ばれ、xargs外部実行プログラムが必要です。以下を使用して(ほぼ)正しく表示される出力を取得できます。

$ find "$(pwd)" -type d | xargs -i sh -c 'pushd "$1"' sh
~/foo ~/foo
~/foo/bar1 ~/foo
~/foo/bar2 ~/foo
~/foo/bar3 ~/foo

ただし、これはシェルを外部プログラムとして実行し、各ディレクトリに対して(独立して)これを行います。これはやや近いです。

$ find "$(pwd)" -type d | xargs sh -c 'for line do pushd "$line"; done' sh
~/foo ~/foo
~/foo/bar1 ~/foo ~/foo
~/foo/bar2 ~/foo/bar1 ~/foo ~/foo
~/foo/bar3 ~/foo/bar2 ~/foo/bar1 ~/foo ~/foo

単一のシェルプロセスを実行し、すべてのディレクトリを繰り返すように指示します。ご覧のとおり、この手法は2回目の試み(および私の答え)に似ており、結果は2回目の試みと同じです。pushd4回呼び出される新しいシェルプロセスが取得され、最終的にAディレクトリスタックが作成されます。つまり、5つのレベルの深さ(開始ディレクトリを2回計算) - しかし、新しいシェルプロセスは子プロセスにあり、次のシェルプロンプトが表示された場合それシェルプロセスが消えた。

ちなみに、コマンドは次のように似ています。 私が数年前にした答えは。  スティーブン・チャジェラスコマンド構造の議論 sh -c long_complex_shell_command shここそしてここ

おすすめ記事