/ bin / sh: pushd: bulunamadı


101

Bir make dosyası içinde aşağıdakileri yapıyorum

pushd %dir_name%

ve aşağıdaki hatayı alıyorum

/bin/sh : pushd : not found

Birisi bana bu hatanın neden ortaya çıktığını söyleyebilir mi? $ PATH değişkenimi kontrol ettim ve / bin içeriyor, bu yüzden bunun bir soruna neden olduğunu düşünmüyorum.


Şikayet etmiyor, bulamadığından şikayet ediyor pushd. Pushd senin içinde $PATHmi?
Konerak

7
Konerak: pushd yolunda olmanın bir anlamı yok, bu bir bash yerleşik. Sorun bir POSIX kabuğu değil, bir bash yerleşik.
Jan Hudec

Kodu neden düzenlediniz?
Jan Hudec

1
Büyük ihtimalle dağıtımınız / bin / sh'yi / bin / bash yerine / bin / ash konumuna taşıdı. Make'inizi özellikle bash kullanmaya zorlamazsanız, / bin / sh ne ise onu kullanacaktır.
stsquad

Bash ile DEĞİL yürütülürse, kabuk betiğinde de aynı sorun meydana gelir.
Vladimir Kroz

Yanıtlar:


113

pushdbashPOSIX tarafından belirlenen Bourne Kabuğu'na yapılan bir geliştirmedir. pushdMevcut çalışma dizini, alt süreçler tarafından değiştirilemeyen bir sürecin bir özelliğidir çünkü bir komut olarak kolayca uygulanamaz. (Bir varsayımsal pushdkomut olabilir yapmak chdir(2)çok kullanışlı olmaz ... çağrıyı ve ardından yeni bir kabuk başlatmak ama.) pushdGibi, bir kabuk yerleşiğidir cd.

Bu nedenle, betiğinizi ya başlamak için değiştirin #!/bin/bashya da geçerli çalışma dizinini bir değişkende saklayın, işinizi yapın ve sonra geri dönün. Çok indirgenmiş sistemlerde çalışan bir kabuk betiği isteyip istemediğinize (örneğin, bir Debian inşa sunucusu) veya her zaman iyi olup olmadığınıza bağlıdır bash.


18
OP, make'den çalıştırıldığını söylüyor. Yani SHELL = /bin/bashkomut dosyası ile başlamak yerine ayar olacaktır #!/bin/bash.
Jan Hudec

@Jan Hudec, ah! İyi yakalama. Teşekkürler.
sarnold

Ancak bu durumda SHELL'in ayarlanması işe yaramayacaktır test1, cevabımda stackoverflow.com/questions/5193048/bin-sh-pushd-not-found/… bakın .
hlovdal

1
@hlovdal: Hayır, gerçekten yeterli olmayacak.
Jan Hudec

1
#!/bin/bashDosyanın ilk satırı olduğundan emin olun .
Michael Cole


18

Bunun için bir çözüm, bir değişkenin mevcut çalışma dizinini alması olabilir. Sonra her şeyi yapmak için cd'den çıkarabilirsin, daha sonra ihtiyacın olduğunda tekrar cd yapabilirsin.

yani

eski yol = `pwd`
# betiğiniz ne yapıyorsa yapın
...
...
...
# itmek istediğin yere geri dön
cd $ eski yol

6
İstediğiniz cddizine de girebilirsiniz ve daha sonra yapın cd -, $oldpatheğer arada kullanmayacaksanız bu değişkeni kullanmanıza gerek yoktur cd. İlginç olan şey pushd, onu her kullandığınızda bir dizini bir yığına itiyor olmanız ve daha sonra kullanarak en son dizine geri dönebilmenizdir popd, bu nedenle birden fazla dizine girip istediğinizde onu kullanmak mantıklıdır. kesin bir geri dönüş.
Enrico

1
Bu sadece bir oneliner ise, aşağıdakiler de işe yarayabilir(cd /new_path ; command )
barney765

10

Bunun nedeni, pushd'nin bash'da yerleşik bir işlev olmasıdır. Bu nedenle, PATH değişkeniyle ilişkili değildir ve ayrıca / bin / sh tarafından desteklenmez (varsayılan olarak make tarafından kullanılır. Bunu SHELL ayarlayarak değiştirebilirsiniz (ancak doğrudan çalışmayacaktır (test1)).

Bunun yerine tüm komutları çalıştırabilirsiniz bash -c "...". Bu, pushd / popd dahil komutların bir bash ortamında (test2) çalışmasını sağlar.

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 ve make test2 çalıştırıldığında aşağıdakileri verir:

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 için, bash bir kabuk olarak kullanılsa bile, kuraldaki her komut / satır kendi başına çalıştırılır, bu nedenle pushd komutu popd'den farklı bir kabukta çalıştırılır.


1
@Jan Hudec, sanırım tcsh(ve belki csh?) > $ tcsh haig:/> exit $ csh haig:/> exit $
İstemlerini

Benimki var :) Aslında benim PS1'im (\u) \h:\w>ama cevap için şimdi genel bir dizgeye indirdim. DOS'taki komut istemi de >varsayılan olarak ( $P$GIIRC) ile bitiyor ve bunu beğendim.
hlovdal


"SHELL = / bin / bash" ayarı benim için iyi çalışıyor, onu nasıl çalıştırdığınızı bilmiyorum.
Isaac Freeman


4

Kabuğunuz (/ bin / sh) 'pushd'yi bulmaya çalışıyor. Ama onu bulamıyor çünkü 'pushd', 'popd' ve bunun gibi diğer komutlar bash içinde oluşturulmuş.

Şu anda yaptığınız gibi Sh yerine Bash (/ bin / bash) kullanarak komut dosyasını başlatın ve çalışacaktır.


2

Diğer yanıtlardan sentezleme: pushdbash'a özgüdür ve siz başka bir POSIX kabuğu kullanıyorsunuz. Farklı dizine ihtiyaç duyan parça için ayrı bir kabuk kullanmak için basit bir geçici çözüm var, bu yüzden şu şekilde değiştirmeyi deneyin:

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

(Uzun yolu bir değişken genişletme ile değiştirdim. Muhtemelen makefile'da bir tane ve açık bir şekilde geçerli dizine genişliyor).

Bunu make'den çalıştırdığınız için, muhtemelen testi de bir make kuralı ile değiştiririm. Sadece

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

(mevcut dizin önekini bıraktı; yine de bazı noktalarda göreceli yol kullanıyordunuz) Ve sadece kuralı bağımlı hale getirmekle kalmaz gen/SvcGenLog. Biraz daha okunabilir olacaktır ve bunu bağlıdır yapabilirsiniz genscript/genmakefile.plböylece de Makefileiçinde genkomut dosyasını değiştirirseniz yeniden oluşturulur. Elbette içeriğinin başka herhangi bir etkisi varsa Makefile, kuralı buna da bağlı hale getirebilirsiniz.


2

Bir make dosyası tarafından çalıştırılan her satırın yine de kendi kabuğunda çalıştırıldığını unutmayın. Dizini değiştirirseniz, sonraki satırları etkilemez. Yani muhtemelen pushd ve popd için çok az kullanımınız var, probleminiz tam tersi, dizinin ihtiyacınız olduğu sürece değişmesini sağlamak!


1

"Apt install bash" komutunu çalıştırın İhtiyacınız olan her şeyi yükleyecek ve komut çalışacaktır.


1

Bu hile yapmalı:

( cd dirname ; pwd ); pwd

Parantezler yeni bir alt kabuk başlatır, böylece cddizini yalnızca alt öğe içindeki değiştirir ve parantez içindeki herhangi bir komut bu klasörde çalışır. Parantezlerden çıktığınızda, daha önce nerede olursanız olun geri dönersiniz ..


1

işte işaret etmek için bir yöntem

sh -> bash

bu komutu terminalde çalıştır

sudo dpkg-reconfigure dash

Bundan sonra görmelisin

ls -l /bin/sh

/ bin / bash'ı işaret edin (ve / bin / dash'i değil)

Referans

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.