¿Cómo ejecuto un programa con un directorio de trabajo diferente del actual, del shell de Linux?

352

Utilizando un shell de Linux , ¿cómo inicio un programa con un directorio de trabajo diferente del directorio de trabajo actual?

Por ejemplo, tengo un archivo binario helloworldque crea el archivo hello-world.txten el directorio actual .

Este archivo está dentro del directorio /a.

Actualmente, estoy en el directorio /b. Quiero comenzar a ejecutar mi programa ../a/helloworldy obtener el hello-world.txtalgún lugar en un tercer directorio /c.

Anton Daneyko
fuente
55
Descubrí el camino difícil que surestablece el directorio de trabajo al directorio de inicio del usuario que especifique antes de ejecutar cualquier -ccomando. Esto fue muy útil para mí.
Patrick M

Respuestas:

561

Llame al programa así:

(cd /c; /a/helloworld)

Los paréntesis hacen que se genere una subcapa. Este sub-shell luego cambia su directorio de trabajo a /c, luego se ejecuta helloworlddesde /a. Una vez que se cierra el programa, el subconjunto finaliza y regresa al indicador del shell principal, en el directorio desde el que comenzó.

Manejo de errores: para evitar ejecutar el programa sin haber cambiado el directorio, por ejemplo, cuando se ha escrito mal /c, haga que la ejecución de helloworldcondicional:

(cd /c && /a/helloworld)

Reducción del uso de memoria: para evitar que el subshell desperdicie memoria mientras se ejecuta hello world, llame a helloworldtravés de exec:

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

[¡Gracias a Josh y Juliano por dar consejos para mejorar esta respuesta!]

David Schmitt
fuente
1
¿Alguna forma de pasar argumentos a este shell? ¿Como en $ 1 y $ 2?
finiteloop
2
@segfault: la subshell tiene acceso completo al alcance circundante.
David Schmitt
Parece que está temporalmente en ese directorio de todos modos, ¿no?
Dhein
1
Puede pasar todos los argumentos haciendo $ *, $ @ o "$ @" (si desea que los argumentos respeten las comillas dobles)
Marcel Valdez Orozco
1
¿Funcionará si agrego esta línea a /etc/rc.d/rc.local?
Pratik Patil
95

Similar a la respuesta de David Schmitt , más la sugerencia de Josh, pero no deja un proceso de shell en ejecución:

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

De esta manera es más similar a la forma en que normalmente ejecuta comandos en el shell. Para ver la diferencia práctica, debe ejecutar ps efdesde otro shell con cada solución.

Juliano
fuente
Bash manual builtins exec
Antonios Hadjigeorgalis
25

Una opción que no requiere una subshell y está integrada en bash

(pushd SOME_PATH && run_stuff; popd)

Manifestación:

$ pwd
/home/abhijit
$ pushd /tmp # directory changed
$ pwd
/tmp
$ popd
$ pwd
/home/abhijit
Loren
fuente
1
A continuación, Sahil ha hecho una sugerencia similar. No funciona si el comando falla. Considere pushd SOME_PATH && run_stuff && popd: si run_stuff falla, entonces popd no se ejecutará.
Anton Daneyko
Respuesta tardía, eso depende de la configuración del archivo bash. Bash puede continuar ejecutando comandos incluso después de un comando fallido (a diferencia de usar &&), pero se puede configurar para que no lo haga usando set -eel archivo y luego no lo hará popd.
Loren
8
Aún así, creo que pushd "${SOME_PATH}" && run_stuff; popdes mejor que la respuesta actual, ya que la semántica pushd / popd se diseñó específicamente para esta situación de ir a algún directorio y luego volver al original.
Marcel Valdez Orozco
¿Cómo funciona como se define como alias y necesito pasar un parámetro?
DrB
Creo que necesitaría escribir un script de shell al que pasaría el parámetro que ejecutaría la serie de comandos, ya que no puede pasar un parámetro en medio de un alias. Si necesita ayuda para escribir eso, debe hacer una pregunta por separado y hacer referencia a esta. Una vez que tenga el script de shell, puede escribir un alias para llamar a su nuevo script.
Loren
19
sh -c 'cd /c && ../a/helloworld'
mihi
fuente
1
Lo usé para jexec de FreeBSD para ejecutar un comando dentro de la cárcel en el directorio de trabajo especificado.
Marián Černý
11

Siempre pienso que las herramientas UNIX deberían escribirse como filtros, leer la entrada de stdin y escribir la salida en stdout. Si es posible, podría cambiar su binario helloworld para escribir el contenido del archivo de texto en stdout en lugar de un archivo específico. De esa manera, puede usar el shell para escribir su archivo en cualquier lugar.

$ cd ~ / b

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

Luther Blisset
fuente
66
+1 por tener razón, aunque la respuesta es solo periféricamente una respuesta.
David Schmitt
8

Simplemente cambie el último "&&" a ";" y devolverá el CD sin importar si el comando falla o tiene éxito:

cd SOME_PATH && run_some_command ; cd -
Johnny Bravo
fuente
4

Una forma de hacerlo es crear un script de shell envoltorio.

El script de shell cambiaría el directorio actual a / c, luego ejecutaría / a / helloworld. Una vez que se cierra el script de shell, el directorio actual vuelve a / b.

Aquí hay un ejemplo de script de shell bash:

#!/bin/bash
cd /c
/a/helloworld
Jin Kim
fuente
2

por qué no hacerlo simple

cd SOME_PATH && run_some_command && cd -

el último comando 'cd' lo llevará de regreso al último directorio pwd. Esto debería funcionar en todos los sistemas * nix.

Sahil
fuente
Estás escribiendo @mezhaka, debería haber considerado eso :)
Sahil
1
Advertencia: si run_some_commandfalla, cd -no se ejecutará.
starbeamrainbowlabs
1

Si siempre desea que vaya a / C, use una ruta absoluta cuando escriba el archivo.

Tom Ritter
fuente
0

Si desea realizar esto dentro de su programa, entonces haría algo como:

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

  // rest of your program...

}
Harold
fuente
Quiere hacer eso en un script de shell, y no en una C. Además, sería una idea horrible subprocesar el archivo binario.
-1

desde el directorio actual proporcione la ruta completa al directorio del script para ejecutar el comando

/root/server/user/home/bin/script.sh
Ravi Bhushan
fuente
1
Eso no cambia en absoluto el directorio de trabajo: creo que está respondiendo una pregunta diferente a la que se le hizo.
Toby Speight
Vine aquí para encontrar una respuesta a la pregunta que respondiste. ¡Gracias! lol
kfrncs