/bin/sh: pushd: не найдено

Я делаю следующее внутри файла make

pushd %dir_name%

и я получаю следующую ошибку:

/bin/sh : pushd : not found

Может кто-нибудь скажет мне, почему эта ошибка появляется? Я проверил свою переменную $PATH, и она содержит /bin, поэтому я не думаю, что это вызывает проблему.

Ответ 1

pushd - это расширение bash для POSIX-указанной Bourne Shell. pushd не может быть легко реализован как команда, потому что текущий рабочий каталог является особенностью процесса, который не может быть изменен дочерними процессами. (Гипотетическая команда pushd может выполнить вызов chdir(2) а затем запустить новую оболочку, но... она не будет очень полезной.) pushd - это встроенная оболочка, как и cd.

Таким образом, либо смените свой скрипт, чтобы начать с #!/bin/bash либо сохраните текущий рабочий каталог в переменной, выполните свою работу, а затем измените ее. Зависит, если вы хотите, чтобы сценарий оболочки работал на очень сжатых системах (например, на сервере сборки Debian), или если вам все равно требуется bash.

Ответ 3

Обходной путь для этого должен состоять в том, чтобы получить переменную в текущем рабочем каталоге. Затем вы можете вывести из него все, чтобы сделать что-нибудь, а затем, когда вам это нужно, вы можете вернуться обратно.

то есть.

oldpath=`pwd`
#do whatever your script does
...
...
...
# go back to the dir you wanted to pushd
cd $oldpath

Ответ 4

Это потому, что 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.

Ответ 5

Ваша оболочка (/bin/sh) пытается найти "pushd". Но он не может найти его, потому что 'pushd', 'popd' и другие команды, подобные этому, строятся в bash.

Запустите script с помощью Bash (/bin/bash) вместо Sh, как вы делаете сейчас, и он будет работать

Ответ 6

Синтезируя из других ответов: 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

(Я заменил длинный путь расширением переменной. Я, вероятно, один в make файле и явно расширяется до текущего каталога).

Поскольку вы запускаете его из 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, поэтому Makefile in gen будет восстановлен, если вы измените script. Конечно, если что-то еще влияет на содержимое Makefile, вы можете заставить правило также зависеть от этого.

Ответ 7

Обратите внимание, что каждая строка, выполняемая файлом make, запускается в своей собственной оболочке. Если вы меняете каталог, это не повлияет на последующие строки. Таким образом, у вас, вероятно, мало пользы для pushd и popd, ваша проблема более противоположна тому, как заставить каталог оставаться неизменным до тех пор, пока вам это нужно!

Ответ 8

Запустите "apt install bash". Он установит все, что вам нужно, и команда будет работать

Ответ 9

sudo dpkg-reconfigure dash 

Затем выберите no.

Ответ 10

Это должно сработать:

( cd dirname ; pwd ); pwd

Скобки запускают новую дочернюю оболочку, поэтому cd изменяет каталог только внутри дочернего, и любая команда после него в скобках будет выполняться в этой папке. Как только вы выйдете из скобок, вы вернетесь туда, где были раньше...