Как запустить программу с рабочим каталогом, отличным от текущего, из оболочки Linux?


352

Как использовать оболочку Linux , как запустить программу с рабочим каталогом, отличным от текущего рабочего каталога?

Например, у меня есть двоичный файл, helloworldкоторый создает файл hello-world.txtв текущем каталоге .

Этот файл находится внутри каталога /a.

В данный момент я в каталоге /b. Я хочу запустить мою программу ../a/helloworldи получить hello-world.txtгде-нибудь в третьем каталоге /c.


5
Я обнаружил сложный способ, с suпомощью которого рабочий каталог сбрасывается в домашний каталог пользователя, которого вы указали, перед выполнением любых -cкоманд. Это было очень полезно для меня.
Патрик М

Ответы:


561

Назовите программу так:

(cd /c; /a/helloworld)

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

Обработка ошибок: Чтобы избежать запуска программы без изменения каталога, например, при наличии ошибки /c, сделайте выполнение helloworldусловия условным:

(cd /c && /a/helloworld)

Сокращение использования памяти: чтобы избежать потери памяти в оболочке во время выполнения hello world, позвоните helloworldчерез exec:

(cd /c && exec /a/helloworld)

[Спасибо Джошу и Джулиано за советы по улучшению этого ответа!]


1
Есть ли способ передать аргументы в эту оболочку? Как в $ 1, так и в $ 2?
finiteloop

2
@segfault: подоболочка имеет полный доступ к окружающей области видимости.
Дэвид Шмитт

Похоже, он временно находится в этом каталоге, не так ли?
Дхейн

1
Вы можете передать все аргументы, выполнив $ *, $ @ или "$ @" (если вы хотите, чтобы аргументы относились к двойным кавычкам)
Марсель Вальдес Орозко

1
Будет ли работать, если я добавлю эту строку в /etc/rc.d/rc.local?
Пратик Патил

95

Аналогичен ответу Дэвида Шмитта , плюс предложение Джоша, но не дает запустить процесс оболочки:

(cd /c && exec /a/helloworld)

Этот способ больше похож на то, как вы обычно запускаете команды в оболочке. Чтобы увидеть практическую разницу, вам нужно запускать ps efиз другой оболочки с каждым решением.



25

Опция, которая не требует подоболочки и встроена в bash

(pushd SOME_PATH && run_stuff; popd)

Демо-версия:

$ pwd
/home/abhijit
$ pushd /tmp # directory changed
$ pwd
/tmp
$ popd
$ pwd
/home/abhijit

1
Подобное предложение было сделано ниже Сахилом. Это не работает, если команда терпит неудачу. Учтите, что pushd SOME_PATH && run_stuff && popdесли run_stuff завершится неудачей, popd не будет выполняться.
Антон Данейко

Поздний ответ, который зависит от настроек bash-файла. Bash может продолжать выполнять команды даже после неудачной команды (в отличие от использования &&), но может быть установлено, что он не будет использовать это set -eв файле, и тогда это не удастся popd.
Лорен

8
Тем не менее, я думаю, что pushd "${SOME_PATH}" && run_stuff; popdэто лучше, чем текущий ответ, так как семантика pushd / popd была специально разработана для этой ситуации, чтобы перейти в какой-то каталог и затем вернуться к исходному.
Марсель Вальдес Орозко

Как это работает, как определено как псевдоним, и мне нужно передать параметр?
DrB

Я думаю, что вам нужно написать сценарий оболочки, которому вы передадите параметр, который будет выполнять серию команд, поскольку вы не можете передать параметр в середине псевдонима. Если вам нужна помощь в написании этого, вы должны задать отдельный вопрос и сослаться на этот. Когда у вас есть скрипт оболочки, вы можете написать псевдоним для вызова вашего нового скрипта.
Лорен

19
sh -c 'cd /c && ../a/helloworld'

1
Используется для jexec FreeBSD для выполнения команды внутри тюрьмы в указанном рабочем каталоге.
Мариан Черны

11

Я всегда думаю, что инструменты UNIX должны быть написаны как фильтры, читать ввод из stdin и записывать вывод в stdout. Если возможно, вы можете изменить свой двоичный файл helloworld, чтобы записать содержимое текстового файла в стандартный вывод, а не в конкретный файл. Таким образом, вы можете использовать оболочку для записи вашего файла в любом месте.

$ cd ~ / b

$ ~ / a / helloworld> ~ / c / helloworld.txt


6
+1 за правоту, хотя ответ только периферийный ответ.
Дэвид Шмитт

8

Просто измените последний "&&" на ";" и он вернется, независимо от того, будет ли команда выполнена неудачно или успешно:

cd SOME_PATH && run_some_command ; cd -

4

Один из способов сделать это - создать скрипт оболочки.

Сценарий оболочки изменит текущий каталог на / c, затем запустит / a / helloworld. После выхода из сценария оболочки текущий каталог возвращается к / b.

Вот пример сценария оболочки bash:

#!/bin/bash
cd /c
/a/helloworld

2

почему бы не сделать это простым

cd SOME_PATH && run_some_command && cd -

последняя команда 'cd' вернет вас в последний каталог pwd. Это должно работать на всех * nix системах.


Вы пишете @mezhaka, должны были это учесть :)
Сахил

1
Предупреждение: если run_some_commandне cd -получится, не будет выполнено.
starbeamrainbowlabs

1

Если вы всегда хотите, чтобы он шел в / C, используйте абсолютный путь при записи файла.


0

Если вы хотите выполнить это внутри вашей программы, то я бы сделал что-то вроде:

#include <unistd.h>
int main()
{
  if(chdir("/c") < 0 )  
  {
     printf("Failed\n");
     return -1 ;
  }

  // rest of your program...

}

Он хочет сделать это в сценарии оболочки, а не в C. Кроме того, было бы ужасной идеей обработать двоичный файл.

-1

из текущего каталога укажите полный путь к каталогу скрипта для выполнения команды

/root/server/user/home/bin/script.sh

1
Это совсем не меняет рабочий каталог - я думаю, что вы отвечаете не на тот вопрос, который был задан.
Тоби Спейт

Пришел сюда, чтобы найти ответ на вопрос, на который вы ответили. Спасибо! LOL
Kfrncs
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.