/ bin / sh: pushd: ไม่พบ


100

ฉันกำลังทำสิ่งต่อไปนี้ภายในไฟล์ make

pushd %dir_name%

และฉันได้รับข้อผิดพลาดต่อไปนี้

/bin/sh : pushd : not found

ใครช่วยบอกฉันหน่อยได้ไหมว่าทำไมข้อผิดพลาดนี้จึงปรากฏขึ้น ฉันตรวจสอบตัวแปร $ PATH ของฉันและมี / bin ดังนั้นฉันจึงไม่คิดว่านั่นทำให้เกิดปัญหา


pushdมันไม่ได้บ่นเกี่ยวกับการดวลจุดโทษก็บ่นว่ามันไม่สามารถหา ผลักดันในของคุณ $PATHหรือไม่?
Konerak

7
Konerak: pushd ไม่มีเหตุผลที่จะอยู่ในเส้นทางมันเป็นการทุบตีในตัว ปัญหาคือbash builtin ไม่ใช่ POSIX shell one
ม.ค. Hudec

ทำไมคุณถึงแก้ไขโค้ดออก?
ม.ค. Hudec

1
เป็นไปได้มากว่า distro ของคุณย้าย / bin / sh ไปที่ / bin / ash แทนที่จะเป็น / bin / bash เว้นแต่คุณจะบังคับให้ Make ของคุณใช้ bash โดยเฉพาะมันจะใช้อะไรก็ได้ / bin / sh คือ
stsquad

ปัญหาเดียวกันจะเกิดขึ้นในเชลล์สคริปต์เช่นกันหากดำเนินการไม่ใช่โดย bash
Vladimir Kroz

คำตอบ:


113

pushdเป็นการbashปรับปรุง Bourne Shell ที่ระบุ POSIX pushdไม่สามารถนำไปใช้เป็นคำสั่งได้อย่างง่ายดายเนื่องจากไดเร็กทอรีการทำงานปัจจุบันเป็นคุณลักษณะของกระบวนการที่กระบวนการย่อยไม่สามารถเปลี่ยนแปลงได้ (สมมุติpushdคำสั่งอาจทำchdir(2)โทรและจากนั้นเริ่มเปลือกใหม่ แต่ ... มันจะไม่สามารถใช้งานได้มาก.) pushdเป็น builtin cdเปลือกเช่นเดียวกับ

ดังนั้นให้เปลี่ยนสคริปต์ของคุณเพื่อเริ่มต้นด้วย#!/bin/bashหรือจัดเก็บไดเร็กทอรีการทำงานปัจจุบันไว้ในตัวแปรทำงานของคุณจากนั้นเปลี่ยนกลับ ขึ้นอยู่กับว่าคุณต้องการเชลล์สคริปต์ที่ทำงานบนระบบลดลงมาก (พูด, การสร้างเซิร์ฟเวอร์ Debian) bashหรือถ้าคุณกำลังดีเสมอที่กำหนด


18
OP บอกว่าทำงานจาก make ดังนั้นมันจะได้รับการตั้งค่ามากกว่าการเริ่มต้นกับสคริปต์SHELL = /bin/bash #!/bin/bash
ม.ค. Hudec

@ จันฮูเด็คอา! จับดี. ขอบคุณ.
sarnold

แต่การตั้งค่า SHELL จะไม่ทำงานในกรณีนี้เห็นtest1ในคำตอบของฉันstackoverflow.com/questions/5193048/bin-sh-pushd-not-found/...
hlovdal

1
@hlovdal: ไม่แน่นอนมันจะไม่เพียงพอ
ม.ค. Hudec

1
ตรวจสอบว่า#!/bin/bashเป็นบรรทัดแรกของไฟล์
Michael Cole

30

เพิ่ม

เปลือก: = / bin / bash

ที่ด้านบนของ makefile ของคุณฉันพบคำถามอื่นฉันจะใช้ Bash syntax ใน Makefile ได้อย่างไร?


ใช่ขอบคุณ. Red Hats เริ่มต้นที่จะทุบตีอย่างไรก็ตามใน Debian มันเป็นเรื่องจริง (หรือการใช้งานบางอย่าง) นั่นคือปัญหาของฉัน
lzap

18

วิธีแก้ปัญหานี้คือการมีตัวแปรรับไดเร็กทอรีการทำงานปัจจุบัน จากนั้นคุณสามารถซีดีออกมาเพื่อทำอะไรก็ได้เมื่อคุณต้องการคุณสามารถกลับเข้าไปในซีดีได้

กล่าวคือ

oldpath = `pwd`
# ทำสิ่งที่สคริปต์ของคุณทำ
...
...
...
# กลับไปที่ผบ. ที่คุณต้องการผลักดัน
cd $ oldpath

6
คุณยังสามารถcdเข้าไปในไดเร็กทอรีที่คุณต้องการและทำหลังจากนั้นcd -ไม่จำเป็นต้องใช้$oldpathตัวแปรนั้นหากคุณจะไม่ใช้cdระหว่าง สิ่งที่น่าสนใจpushdคือทุกครั้งที่คุณใช้งานคุณกำลังผลักดันไดเร็กทอรีลงในสแต็กและหลังจากนั้นคุณสามารถกลับไปใช้ไดเร็กทอรีล่าสุดpopdได้ดังนั้นจึงเหมาะสมที่จะใช้เมื่อคุณเข้าสู่มากกว่าหนึ่งไดเร็กทอรีและต้องการ ทางกลับแน่นอน
Enrico

1
หากเป็นเพียงแค่ oneliner สิ่งต่อไปนี้อาจใช้ได้เช่นกัน(cd /new_path ; command )
barney765

10

เนื่องจาก pushd เป็นฟังก์ชัน builtin ใน 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 และทำการ 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>แต่ฉันเพิ่งถอดมันลงไปเป็นสตริงทั่วไปเพื่อหาคำตอบ พรอมต์ใน DOS ก็ลงท้ายด้วย>โดยค่าเริ่มต้น ( $P$GIIRC) และฉันก็ชอบมัน
hlovdal

ตั้ง SHELL ด้วย: = not with =
cup

การตั้งค่า "SHELL = / bin / bash" ใช้ได้ดีสำหรับฉันไม่แน่ใจว่าคุณทำให้มันไม่ทำงานได้อย่างไร
Isaac Freeman


4

เชลล์ของคุณ (/ bin / sh) กำลังพยายามค้นหา "pushd" แต่หาไม่เจอเพราะคำสั่ง 'pushd', 'popd' และคำสั่งอื่น ๆ เช่นนั้น build in bash

เรียกใช้สคริปต์ของคุณโดยใช้ Bash (/ bin / bash) แทน Sh เหมือนที่คุณกำลังทำอยู่ตอนนี้และจะใช้งานได้


2

การสังเคราะห์จากการตอบกลับอื่น ๆ : pushdเป็นแบบ bash โดยเฉพาะและคุณกำลังทำโดยใช้ POSIX เชลล์อื่น มีวิธีแก้ปัญหาง่ายๆในการใช้เชลล์แยกสำหรับส่วนที่ต้องการไดเร็กทอรีอื่นดังนั้นลองเปลี่ยนเป็น:

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

(ฉันแทนที่เส้นทางยาวด้วยการขยายตัวแปรฉันอาจเป็นหนึ่งใน makefile และขยายไปยังไดเร็กทอรีปัจจุบันอย่างชัดเจน)

เนื่องจากคุณเรียกใช้จาก make ฉันอาจจะแทนที่การทดสอบด้วย make rule ด้วย แค่

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

(ทิ้งคำนำหน้าไดเรกทอรีปัจจุบันคุณกำลังใช้เส้นทางสัมพัทธ์ในบางจุดอยู่ดี) และกว่าจะทำให้กฎขึ้นอยู่กับgen/SvcGenLog. มันจะอ่านง่ายขึ้นเล็กน้อยและคุณสามารถทำให้มันขึ้นอยู่กับสิ่งgenscript/genmakefile.plนั้นได้ดังนั้นMakefileอินgenจะถูกสร้างใหม่หากคุณแก้ไขสคริปต์ แน่นอนว่าหากมีสิ่งอื่นใดที่ส่งผลกระทบต่อเนื้อหาของกฎMakefileคุณสามารถทำให้กฎขึ้นอยู่กับสิ่งนั้น


2

โปรดทราบว่าแต่ละบรรทัดที่ดำเนินการโดยไฟล์ make จะรันในเชลล์ของตัวเองอยู่ดี หากคุณเปลี่ยนไดเร็กทอรีจะไม่มีผลกับบรรทัดถัดไป ดังนั้นคุณอาจใช้ pushd และ popd เพียงเล็กน้อยปัญหาของคุณกลับตรงกันข้ามมากกว่านั่นคือการทำให้ไดเร็กทอรีมีการเปลี่ยนแปลงนานเท่าที่คุณต้องการ!


1

เรียกใช้ "apt install bash" มันจะติดตั้งทุกสิ่งที่คุณต้องการและคำสั่งจะทำงาน


1

สิ่งนี้ควรทำเคล็ดลับ:

( cd dirname ; pwd ); pwd

วงเล็บเริ่มเชลล์ลูกใหม่ดังนั้นการcdเปลี่ยนแปลงไดเร็กทอรีภายในชายด์เท่านั้นและคำสั่งใด ๆ หลังจากนั้นภายในวงเล็บจะทำงานในโฟลเดอร์นั้น เมื่อคุณออกจากวงเล็บคุณจะกลับมาที่ใดก็ตามที่คุณเคยอยู่มาก่อน ..


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.