2011-05-25 16 views
8

Me gustaría saber si es posible cambiar el directorio de la terminal actual desde donde estoy ejecutando mi script de ruby.Cómo (terminal) cd en la carpeta de la secuencia de comandos de ruby ​​

Por ejemplo, si estoy ejecutando el script desde $HOME en el terminal, me gustaría hacer un cd en $HOME/mydir al final del script.

He intentado un par de cosas, pero siempre encuentro en la misma dirección donde se inició el guión.

cosas que he intentado:

Dir.chdir(mydir) 
%[cd mydir] 

que realmente hacen de cambio de directorio, pero sólo en el hilo de la ejecución del script. Cuando finaliza el guión, mi ubicación actual en la terminal sigue siendo la misma que tenía antes de iniciar el guión.

He encontrado algo similar en SO, pero es Python-related y la respuesta parece negativa.


Puede preguntar por qué?

Actualmente estoy involucrado en una aplicación de línea de comandos (usando gli) que, como punto de partida, necesita una carpeta de proyecto. Así que mi primer comando es así:

$ myfoo new project 

que crea una nueva carpeta con el nombre project en el directorio actual. Ahora, para ser capaz de trabajar con los otros comandos que necesito:

$ cd project 
project$ myfoo domore 

Así que era simplemente pensando que sería bueno para fundar mi propia en project después de haber ejecutado myfoo new project.


Como tenía miedo, no es tan fácil (no es posible en absoluto). Entonces, ¿qué pasa con el uso de un script bash que hace las llamadas ruby ​​que quiero, en lugar del archivo estándar generado por RubyGems? ¿Es eso factible? ¿Soy tonto? ¿Debo usar eval?


Gracias por las respuestas. Pero me temo que nadie es aceptable. Probablemente la pregunta no fue :).

+0

Parece poco probable que pueda hacer esto. Todas las llamadas al sistema desde ruby ​​operan en un hilo diferente de su script/shell, y no tendrían ningún efecto en la ubicación actual. ¿Para qué esperas usar esto? –

+0

@ Douglas-F-Shearer: He ampliado mis razones un poco en la respuesta –

+0

solo por curiosidad, ¿por qué no funcionó mi respuesta? He usado esta técnica un par de veces, y no estoy seguro de cómo no se ajusta a tu situación. – Ian

Respuesta

2

Esto no es posible, que yo sepa, ya que son procesos diferentes. Si necesita afectar el proceso padre de la secuencia de comandos de Ruby (Bash), Bash necesitará obtener algo. Por lo tanto, podría hacer que su script de Ruby imprima algunos comandos bash, y luego tener un contenedor Bash que genere la salida de Ruby.

Trate esto como un ejemplo, en Bash:

`ruby -e 'puts "cd /tmp"'` | source /dev/stdin 

But this will only work in Bash 4.0.

EDIT:

realidad, se puede hacer esto con eval lugar de origen en Bash 3:

eval $(ruby -e'puts "cd /tmp"') 
+0

Ok, pero termino en mi script con '% [eval $ (ruby -e'puts" cd/tmp "')]', lo cual no hace ninguna diferencia. –

+0

, porque está generando un proceso Bash (un nieto del proceso Bash al que desea afectar), evalúa su código y luego lo deja morir. Necesita ejecutar eval directamente en el proceso Bash que desea cambiar. Más tarde, puedes arreglarlo con un alias o algo así. – Ian

+0

He extendido la respuesta que pregunta la cosa al revés. –

2

Dudo que haya una forma directa de hacerlo.

Cuando inicia un programa desde su shell de inicio de sesión, debajo de la campana está haciendo fork/exec lo que significa que se crea un nuevo proceso (hijo) (que tiene su propio entorno, como el directorio de trabajo actual)/output/error streams están asociados con el proceso de shell (principal). Entonces, cuando su script llama al Dir.chdir, cambia el directorio de trabajo actual para el proceso de script (hijo), no el padre.

Tal vez su secuencia de comandos podría ejecutar un shell nuevo antes de que se cierre, por lo que parece que su terminal ha cambiado de directorio. Aunque, tendría que salir de ese shell adicional antes de salir de la sesión de su terminal ...

+0

He extendido la respuesta que pregunta la cosa al revés. –

0

Midnight Commander lo hace, mediante el uso de un alias de shell y un script de envoltura.

La envoltura es para enviar a un directorio determinado por el contenido de un archivo escrito por mc (1) al salir, y el alias se usa para source envoltorio, lo que lo hace ejecutar en el shell de inicio de sesión. de la subshell que se habría bifurcado, si la secuencia de comandos se hubiera iniciado normalmente.

Con todo, esto le permite cambiar el directorio de trabajo actual al salir.

Para hacer esto, necesitaría duplicar la funcionalidad de alias/envoltura. Consulte http://midnight-commander.org/browser/contrib para saber cómo lo hicieron.

+0

¿Hay alguna documentación sobre? ¿Cómo aplico esto a mi caso de uso? –

+0

esto es lo mismo que mi respuesta. – Ian

1

Tal vez un poco más fácil,

Se puede utilizar en combinación con exec Maerics post acerca de la creación de una nueva shell bash interior de rubí para lograrlo.

exec ruby -e "Dir.chdir('mydir'); exec 'bash'" 

exec reemplazará el proceso padre (shell) con el proceso hijo (rubí), por lo tanto la cáscara ya no existe (sin necesidad de salir).

Al final de la rutina de ruby, bash se dispara (nuevamente con exec esta vez en ruby) en el nuevo directorio y reemplaza el proceso de ruby.

+0

¿Cómo puedo integrar esto con un rubygem que tiene su propio comando, como el que se describe en la respuesta? –

+0

@empo Al final, el script de ruby ​​agrega 'exec 'bash''. Desde la línea de comando, modifique la llamada para que sea 'exec myfoo new project'. Esto sigue siendo torpe :( – diedthreetimes

Cuestiones relacionadas