/ bin / sh: pushd: tidak ditemukan

99

Saya melakukan hal berikut di dalam file make

pushd %dir_name%

dan saya mendapatkan kesalahan berikut

/bin/sh : pushd : not found

Bisakah seseorang memberi tahu saya mengapa kesalahan ini muncul? Saya memeriksa variabel $ PATH saya dan mengandung / bin jadi saya tidak berpikir itu menyebabkan masalah.

Pein
sumber
Ini tidak mengeluh tentang sh, itu mengeluh tidak dapat ditemukan pushd. Apakah pushd ada di dalam Anda $PATH?
Konerak
7
Konerak: pushd tidak masuk akal berada di jalur, ini adalah bash bawaan. Masalahnya adalah bash builtin, bukan shell POSIX.
Jan Hudec
Mengapa Anda mengedit kode?
Jan Hudec
1
Kemungkinan besar distro Anda telah pindah / bin / sh ke / bin / ash daripada / bin / bash. Kecuali Anda secara khusus memaksa Make Anda untuk menggunakan bash, itu akan menggunakan / bin / sh apa pun itu.
stsquad
Masalah yang sama akan terjadi pada skrip shell juga jika dijalankan BUKAN oleh bash.
Vladimir Kroz

Jawaban:

113

pushdadalah bashpeningkatan pada Bourne Shell yang ditentukan oleh POSIX. pushdtidak dapat dengan mudah diimplementasikan sebagai perintah, karena direktori kerja saat ini adalah fitur dari proses yang tidak dapat diubah oleh proses anak. ( pushdPerintah hipotetis mungkin melakukan chdir(2)panggilan dan kemudian memulai shell baru, tetapi ... itu tidak akan terlalu bisa digunakan.) pushdAdalah shell bawaan, sama seperti cd.

Jadi, ubah skrip Anda untuk memulai #!/bin/bashatau simpan direktori kerja saat ini dalam variabel, lakukan pekerjaan Anda, lalu ubah kembali. Tergantung apakah Anda menginginkan skrip shell yang bekerja pada sistem yang sangat berkurang (katakanlah, server build Debian) atau jika Anda baik-baik saja selalu membutuhkan bash.

sarnold
sumber
17
OP mengatakan itu dijalankan dari make. Jadi itu akan menjadi pengaturan SHELL = /bin/bashdaripada memulai skrip dengan #!/bin/bash.
Jan Hudec
@ Jan Hudec, ah! Tangkapan yang bagus. Terima kasih.
sarnold
Tetapi pengaturan SHELL tidak akan berfungsi dalam kasus ini, lihat test1di jawaban saya, stackoverflow.com/questions/5193048/bin-sh-pushd-not-found/… .
hlovdal
1
@hlovdal: Tidak, memang itu tidak akan cukup.
Jan Hudec
1
Pastikan #!/bin/bashbaris pertama file tersebut.
Michael Cole
29

Menambahkan

KULIT: = / bin / bash

di bagian atas makefile Anda, saya menemukannya di pertanyaan lain Bagaimana cara menggunakan sintaks Bash di target Makefile?

Juan Jose Pablos
sumber
Ya terima kasih. Red Hats default untuk bash tetapi di Debian itu benar-benar sh (atau beberapa penerapannya). Itu masalah saya.
lzap
18

Solusi untuk ini adalah memiliki variabel untuk mendapatkan direktori kerja saat ini. Kemudian Anda dapat cd keluar untuk melakukan apa pun, lalu ketika Anda membutuhkannya, Anda dapat kembali masuk.

yaitu

oldpath = `pwd`
#melakukan apa pun yang dilakukan skrip Anda
...
...
...
# kembali ke direktori yang ingin Anda tekan d
cd $ oldpath
Rahasia
sumber
6
Anda juga dapat cdmasuk ke direktori yang Anda inginkan dan setelah itu melakukannya cd -, tidak perlu menggunakan $oldpathvariabel itu jika Anda tidak akan menggunakan cdinbetween. Hal yang menarik tentang pushdadalah bahwa setiap kali Anda menggunakannya, Anda mendorong direktori ke dalam tumpukan, dan setelah itu Anda dapat kembali ke yang terbaru menggunakan popd, jadi masuk akal untuk menggunakannya ketika Anda masuk ke lebih dari satu direktori dan ingin jalan kembali yang pasti.
Enrico
1
Jika itu hanya satu perjalanan, berikut ini juga dapat bekerja(cd /new_path ; command )
barney765
10

Ini karena pushd adalah fungsi bawaan di bash. Jadi tidak terkait dengan variabel PATH dan juga tidak didukung oleh / bin / sh (yang digunakan secara default oleh make. Anda dapat mengubahnya dengan menyetel SHELL (meskipun tidak akan bekerja secara langsung (test1)).

Anda malah bisa menjalankan semua perintah melalui bash -c "...". Itu akan membuat perintah, termasuk pushd / popd, berjalan di lingkungan 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;"

Saat menjalankan make test1 dan make test2 memberikan yang berikut ini:

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>

Untuk test1, meskipun bash digunakan sebagai shell, setiap perintah / baris dalam aturan dijalankan dengan sendirinya, sehingga perintah pushd dijalankan di shell yang berbeda dengan popd.

hlovdal.dll
sumber
1
@ Jan Hudec, saya pikir tcsh(dan mungkin csh?) Mengakhiri > $ tcsh haig:/> exit $ csh haig:/> exit $
permintaan
Milik saya tidak :) Sebenarnya PS1 saya adalah (\u) \h:\w>tetapi saya baru saja melepaskannya ke string generik sekarang untuk jawabannya. Prompt di DOS juga diakhiri dengan >default ( $P$GIIRC), dan saya suka itu.
hlovdal
Setel SHELL dengan: = tidak dengan =
cup
Pengaturan "SHELL = / bin / bash" berfungsi dengan baik untuk saya, tidak yakin bagaimana Anda membuatnya tidak berfungsi.
Isaac Freeman
4

Shell Anda (/ bin / sh) mencoba mencari 'pushd'. Tetapi tidak dapat menemukannya karena 'pushd', 'popd' dan perintah lain seperti itu dibuat di bash.

Luncurkan skrip Anda menggunakan Bash (/ bin / bash) daripada Sh seperti yang Anda lakukan sekarang, dan itu akan berhasil

joseignaciorc.dll
sumber
4
sudo dpkg-reconfigure dash 

Lalu pilih no.

pengguna2438597
sumber
2

Mensintesis dari tanggapan lain: pushdbersifat khusus bash dan Anda membuat menggunakan shell POSIX lain. Ada solusi sederhana untuk menggunakan shell terpisah untuk bagian yang membutuhkan direktori berbeda, jadi coba ubah ke:

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

(Saya mengganti jalur panjang dengan perluasan variabel. Saya mungkin adalah salah satu di makefile dan secara jelas meluas ke direktori saat ini).

Karena Anda menjalankannya dari make, saya mungkin akan mengganti tes dengan aturan make juga. Hanya

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

(hilangkan awalan direktori saat ini; Anda masih menggunakan jalur relatif di beberapa titik) Dan daripada hanya membuat aturan bergantung gen/SvcGenLog. Ini akan sedikit lebih mudah dibaca dan Anda dapat membuatnya bergantung genscript/genmakefile.pljuga, jadi Makefilein genakan dibuat ulang jika Anda memodifikasi skrip. Tentu saja jika ada hal lain yang memengaruhi konten Makefile, Anda dapat membuat aturan bergantung padanya juga.

Jan Hudec
sumber
2

Perhatikan bahwa setiap baris yang dieksekusi oleh file make tetap dijalankan di cangkangnya sendiri. Jika Anda mengubah direktori, itu tidak akan mempengaruhi baris berikutnya. Jadi Anda mungkin hanya memiliki sedikit kegunaan untuk pushd dan popd, masalah Anda lebih kebalikannya, yaitu membuat direktori tetap berubah selama Anda membutuhkannya!

Mark Baker
sumber
1

Jalankan "apt install bash" Ini akan menginstal semua yang Anda butuhkan dan perintah akan bekerja

MatanN
sumber
1

berikut adalah metode untuk menunjukkan

sh -> pesta

jalankan perintah ini di terminal

sudo dpkg-reconfigure dash

Setelah ini, Anda akan melihatnya

ls -l /bin/sh

arahkan ke / bin / bash (dan bukan ke / bin / tanda hubung)

Referensi

Muhammad Numan
sumber
0

Ini harus melakukan trik:

( cd dirname ; pwd ); pwd

Tanda kurung memulai cangkang anak baru, sehingga cdmengubah direktori di dalam anak saja, dan perintah apa pun setelahnya di dalam tanda kurung akan berjalan di folder itu. Setelah Anda keluar dari tanda kurung, Anda kembali ke tempat Anda sebelumnya ..

Born2Smile
sumber