/ bin / sh:pushd:見つかりません


99

私はメイクファイル内で次のことをしています

pushd %dir_name%

そして私は次のエラーを受け取ります

/bin/sh : pushd : not found

誰かがこのエラーが表示されている理由を教えてもらえますか?$ PATH変数を確認したところ、/ binが含まれているため、問題が発生しているとは思われません。


それはshについて文句を言うのではなく、見つけることができないと文句を言うことpushdです。あなたの中に押し込まれています $PATHか?
Konerak

7
Konerak:pushdがパスにあるのは意味がありません。これはbashビルトインです。問題はPOSIXシェルの問題ではなく、bashの組み込みです。
Jan Hudec

なぜコードを編集したのですか?
Jan Hudec

1
ディストリビューションが/ bin / shを/ bin / bashではなく/ bin / ashに移動した可能性があります。Makeでbashを使用するように強制しない限り、/ bin / shが使用されます。
stsquad

同じ問題がbash以外で実行された場合にもシェルスクリプトで発生します。
Vladimir Kroz 2015年

回答:


113

pushdあるbashPOSIX指定ボーンシェルに強化。pushd現在の作業ディレクトリは子プロセスで変更できないプロセスの機能であるため、コマンドとして簡単に実装することはできません。(架空のpushdコマンドchdir(2)呼び出しを行ってから新しいシェルを開始する可能性がありますが、それpushdはあまり使い道がありません。)と同様に組み込みのシェルcdです。

そのため、スクリプトを最初から変更するか#!/bin/bash、現在の作業ディレクトリを変数に格納し、作業を行ってから元に戻します。非常に削減されたシステム(たとえば、Debianビルドサーバー)で動作するシェルスクリプトが必要か、または常に必要な場合に依存しますbash


17
OPはmakeから実行されると言います。そのためSHELL = /bin/bash、スクリプトをで開始するのではなく設定し#!/bin/bashます。
Jan Hudec

@Jan Hudec、ああ!良いキャッチ。ありがとう。
サルノルド

しかし、SHELLを設定してもこの場合は機能しません。test1私の答えであるstackoverflow.com/questions/5193048/bin-sh-pushd-not-found/…を参照してください。
hlovdal、2011年

1
@hlovdal:いいえ、確かにそれだけでは十分ではありません。
Jan Hudec

1
#!/bin/bashファイルの最初の行を確認してください。
Michael Cole


18

これの回避策は、変数に現在の作業ディレクトリを取得させることです。それから、あなたはそれからcdして何でもすることができ、それが必要なときにcdして戻すことができます。

すなわち

oldpath = `pwd`
#スクリプトが行うことをすべて実行します
...
...
...
#pushdしたいディレクトリに戻ります
cd $ oldpath

6
必要なcdディレクトリに移動して、後で実行することもできます。中間で使用しない場合cd -は、その$oldpath変数を使用する必要はありませんcd。興味深い点pushdは、それを使用するたびにディレクトリをスタックにプッシュし、後でを使用して最新のディレクトリに戻ることができるpopdため、複数のディレクトリに移動して必要な場合にそれを使用することは理にかなっています確かな帰り道。
Enrico

1
ワンライナーの場合は、次も機能する可能性があります(cd /new_path ; command )
barney765

10

これは、pushdがbashの組み込み関数であるためです。そのため、PATH変数とは関係なく、/ bin / sh(makeによってデフォルトで使用されます。SHELLを設定することで変更できます(直接動作しません(test1)))。

代わりに、すべてのコマンドをから実行できますbash -c "..."。これにより、pushd / popdを含むコマンドがbash環境(test2)で実行されます。

SHELL = /bin/bash

test1:
        @echo before
        @pwd
        @pushd /tmp
        @echo in /tmp
        @pwd
        @popd
        @echo after
        @pwd

test2:
        @/bin/bash -c "echo before;\
        pwd; \
        pushd /tmp; \
        echo in /tmp; \
        pwd; \
        popd; \
        echo after; \
        pwd;"

make test1とmake test2を実行すると、次のようになります。

prompt>make test1
before
/download/2011/03_mar
make: pushd: Command not found
make: *** [test1] Error 127
prompt>make test2
before
/download/2011/03_mar
/tmp /download/2011/03_mar
in /tmp
/tmp
/download/2011/03_mar
after
/download/2011/03_mar
prompt>

test1の場合、bashがシェルとして使用されていても、ルールの各コマンド/行はそれ自体で実行されるため、pushdコマンドはpopdとは異なるシェルで実行されます。


1
@Jan Hudec、プロンプトはtcsh(おそらくcsh?)で終わると思います> $ tcsh haig:/> exit $ csh haig:/> exit $
sarnold

私のPS1は実際には:)です(\u) \h:\w>が、私のPS1は実際にそうですが、答えを出すために今、それを一般的な文字列に削除しました。DOSのプロンプトも>デフォルトで終了しています($P$GIIRC)。
hlovdal、2011年

シェルを:=ではなく=で設定する
カップ

"SHELL = / bin / bash"を設定するとうまくいきますが、どうすればうまくいかないのかわかりません。
Isaac Freeman

4

シェル(/ bin / sh)が 'pushd'を見つけようとしています。しかし、「pushd」、「popd」、およびそのような他のコマンドはbashに組み込まれているため、それを見つけることができません。

今のように、Shの代わりにBash(/ bin / bash)を使用してスクリプトを起動すると、動作します



2

他の応答からの合成:pushdbash固有であり、別のPOSIXシェルを使用している。別のディレクトリが必要な部分に別のシェルを使用する簡単な回避策があるので、次のように変更してみてください。

test -z gen || mkdir -p gen \
 && ( cd $(CURRENT_DIRECTORY)/genscript > /dev/null \
 && perl genmakefile.pl \
 && mv Makefile ../gen/ ) \
 && echo "" > $(CURRENT_DIRECTORY)/gen/SvcGenLog

(私は長いパスを変数展開に置き換えました。私はおそらくメイクファイルにあるパスであり、現在のディレクトリに明らかに展開されます)。

makeから実行しているので、おそらくテストもmakeルールに置き換えます。ただ

gen/SvcGenLog :
    mkdir -p gen
    cd genscript > /dev/null \
     && perl genmakefile.pl \
     && mv Makefile ../gen/ \
    echo "" > gen/SvcGenLog

(現在のディレクトリプレフィックスを削除しました。とにかくいくつかの点で相対パスを使用していました)そして、ルールをに依存させるだけではありませんgen/SvcGenLog。少し読みやすくなり、依存するようにできるgenscript/genmakefile.plので、スクリプトを変更するとMakefilein genが再生成されます。もちろん、何かがのコンテンツに影響を与えるMakefile場合は、ルールもそれに依存するようにできます。


2

makeファイルによって実行される各行は、とにかく独自のシェルで実行されることに注意してください。ディレクトリを変更しても、以降の行には影響しません。したがって、おそらくpushdとpopdの使用はほとんどありません。問題は、その反対であり、必要な間ディレクトリを変更したままにすることです。


1

「apt install bash」を実行すると、必要なものがすべてインストールされ、コマンドが機能します


1

ここにポイントする方法があります

sh-> bash

端末でこのコマンドを実行します

sudo dpkg-reconfigure dash

この後、あなたは見るべきです

ls -l /bin/sh

/ bin / bashを指す(/ bin / dashを指すのではない)

参照


0

これはトリックを行うべきです:

( cd dirname ; pwd ); pwd

括弧は新しい子シェルを開始するため、cdは子内のディレクトリのみを変更し、括弧内のその後のコマンドはそのフォルダーで実行されます。かっこを終了すると、以前の場所に戻ります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.