¿Cómo ejecutar un comando con un directorio como argumento, luego cd al mismo? Me sale "no hay tal archivo o directorio"


15

Me gustaría construir una función corta para hacer lo siguiente. Digamos que muevo el archivo 'file.tex' a mi directorio de documentos:

mv file.tex ~/Documents

Entonces, me gustaría ir cda ese directorio:

cd ~/Documents

Me gustaría generalizar esto a cualquier directorio, para poder hacer esto:

mv file.tex ~/Documents
follow

y haga que el followcomando lea el destino del comando anterior, luego ejecútelo en consecuencia. Para un directorio simple, esto no ahorra mucho tiempo, pero cuando se trabaja con directorios anidados, sería tremendo poder usar

mv file.tex ~/Documents/folder1/subfolder1
follow

Pensé que sería relativamente simple y que podría hacer algo como esto:

follow()
{
    place=`history 2 | sed -n '1p;1q' | rev | cut -d ' ' -f1 | rev`
    cd $place
}

Pero esto no parece funcionar. Si hago eco $place, obtengo la cadena deseada (la estoy probando ~/Documents), pero el último comando devuelve

No such file or directory

El directorio ciertamente existe. Estoy perdido ¿Podrías ayudarme?


Me gustaría señalar que si no le importa mantener file.texla ubicación original, los enlaces simbólicos son una muy buena alternativa, ya que solo tiene que vincular una vez, y siempre apuntará a la última versión.
Kroltan

55
Forma más fácil: escriba cd alt + .para sustituir el último token del comando anterior. Repita para ir más atrás en la historia de los tokens finales. (Digo token no arg, porque foo &toma &como token final). Puedes usar un argumento numérico (con escape-3 alt +. Por ejemplo).
Peter Cordes


Respuestas:


18

En lugar de definir una función, puede usar la variable $_, que se expande al último argumento del comando anterior mediante bash. Entonces usa:

cd "$_"

después del mvcomando

También puedes usar la expansión del historial:

cd !:$

Si debe usar una función:

follow () { cd "$_" ;}

$ follow () { cd "$_" ;}
$ mv foo.sh 'foo bar'
$ follow 
foo bar$ 

NB: Esta respuesta está dirigida al formato exacto de argumentos de línea de comando que ha utilizado, ya que estamos tratando con parámetros posicionales. Para otros formatos mv -t foo bar.txt, por ejemplo , es necesario incorporar comprobaciones específicas de antemano, entonces sería apropiado un contenedor.


Su expansión de historial (cd!: $) Funciona perfectamente. Gracias. Sin embargo, el otro (cd "$ _") no: mv file.tex ~ / Downloads / cd "$ _" bash: cd: __bp_preexec_invoke_exec: No existe tal archivo o directorio. Con mucho gusto aceptaré su respuesta como totalmente correcta, y gracias.
Fuego

Siempre he escrito (un tanto derrochador) cd !$o cd $(dirname !$). ¡No sabía sobre la $_variable!
Kalvin Lee

Ahora, ¿qué pasa si lo hago en mv -t ~/Documents file.texlugar de mv file.tex ~/Documents? En pocas palabras, no estoy seguro de que esto se mvpueda resolver en el caso general ... una función envolvente o que los reimplementos podrían ser mejores ...
un CVn

@ MichaelKjörling no funcionará simplemente ... este ejemplo es solo para cubrir el caso que OP tiene, no los casos de borde (o todos) ...
heemayl

No necesitas el colon; !$es equivalente !:$y más rápido de escribir.
Comodín

14

Con las combinaciones de teclas bash estándar, la combinación Alt.copiará el último argumento de la línea de comando anterior en el actual. Entonces, escribiendo

$ mv foo ~/some/long/path/
$ cd <Alt><.>

cedería

$ mv foo ~/some/long/path/
$ cd ~/some/long/path/

y sería incluso menos tipeado que la palabra follow.

Para mayor conveniencia, la repetición de la Alt.combinación buscará los últimos argumentos de todas las líneas de comando anteriores.

Anexo: El nombre del comando bash correspondiente a esta combinación de teclas es yank-last-argo insert-last-argument. Se puede encontrar en la página de manual de bash en "Comandos para manipular el historial" o en el Manual de referencia de Bash más exhaustivo ).


1
Eso es inteligente. ¡Gracias! No tenía idea de que esto existía.
Fuego

@Fire Agregué referencias para esos comandos, para que pueda encontrar muchas más combinaciones de teclas interesantes (e inmediatamente las olvide de nuevo, como siempre hago).
Dubu

1
También se puede utilizar <esc>a continuación .para obtener el mismo resultado que <alt>+., esto, tiene utilidad cuando se tiene BloqMayus reasigna a escapar :)
gnur

1
@gnur vi (m) usuario, supongo. ;-)
Dubu

6

Es casi seguro que se encuentra con el problema de que la expansión de tilde tiene lugar antes de la expansión de parámetros, lo que puede explicarse con un breve ejemplo:

$ cd ~kaz
kaz $ var='~kaz'
kaz $ echo $var
~kaz
kaz $ cd $kaz
bash: cd: ~kaz: No such file or directory

Esto se puede abordar con eval. De todos modos, vas a necesitar eval, porque estás extrayendo comandos del historial y pueden contener expansiones arbitrarias, como:

$ mv file.tex ~/Documents/$(compute_folder_name foo-param)/subfolder1
$ follow

(Hay problemas, como que la reexpansión de estos valores puede que ya no coincida con la expansión original que se produjo. Supongamos que compute_folder_namees una función que incrementa alguna variable global).


44
No es necesario eval. (Nunca.) Pero es bueno detectar los problemas de la secuencia de expansión. Si menciona la mayor conveniencia de la expansión de la historia para usar evalaquí, esta será la mejor respuesta en mi opinión; ninguno de los otros explica realmente por qué la solución del Cartel original no funcionó.
Comodín
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.