Как запустить программу с рабочим каталогом, отличным от текущего, из оболочки 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из другой оболочки с каждым решением.

Жулиано
источник
Bash ручной встроенный exec
Антониос Hadjigeorgalis
25

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

(pushd SOME_PATH && run_stuff; popd)

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

$ pwd
/home/abhijit
$ pushd /tmp # directory changed
$ pwd
/tmp
$ popd
$ pwd
/home/abhijit
Loren
источник
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 -
JohnnyBravo
источник
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