scripts script resueltos programas programacion pasar parametros ejercicios ejemplos bash shell unix pipe

bash - script - ¿Cómo ejecutar la salida de un comando dentro del shell actual?



scripts bash ejemplos (9)

Soy muy consciente de la utilidad source (aka . ), Que tomará los contenidos de un archivo y los ejecutará dentro del shell actual.

Ahora, estoy transformando algunos textos en comandos de shell, y luego ejecutándolos, de la siguiente manera:

$ ls | sed ... | sh

Es solo un ejemplo al azar, el texto original puede ser cualquier cosa. sed también, solo un ejemplo para transformar el texto. El bit interesante es sh . Me pipe todo lo que tengo que sh y lo ejecuta.

Mi problema es que eso significa comenzar un nuevo submarino. Prefiero que los comandos se ejecuten dentro de mi caparazón actual. Como podría hacer con source some-file , si tuviera los comandos en un archivo de texto.

No quiero crear un archivo temporal porque me siento sucio.

Alternativamente, me gustaría comenzar mi caparazón secundario con las mismas características exactas que mi caparazón actual.

actualizar

Bien, las soluciones que usan reveses ciertamente funcionan, pero a menudo necesito hacer esto mientras estoy revisando y cambiando el resultado, por lo que preferiría que hubiera una forma de canalizar el resultado en algo al final.

triste actualización

Ah, la cosa /dev/stdin veía tan bonita, pero, en un caso más complejo, no funcionó.

Entonces, tengo esto:

find . -type f -iname ''*.doc'' | ack -v ''/.doc$'' | perl -pe ''s/^((.*)/.doc)$/git mv -f $1 $2.doc/i'' | source /dev/stdin

Lo que garantiza que todos los archivos .doc tengan su extensión en minúsculas.

Y que, por cierto, puede manejarse con xargs , pero eso es además del punto.

find . -type f -iname ''*.doc'' | ack -v ''/.doc$'' | perl -pe ''s/^((.*)/.doc)$/$1 $2.doc/i'' | xargs -L1 git mv

Entonces, cuando ejecute el primero, saldrá inmediatamente, no pasa nada.


¿Por qué no usar la source entonces?

$ ls | sed ... > out.sh ; source out.sh


Creo que esta es "la respuesta correcta" a la pregunta:

ls | sed ... | while read line; do $line; done

Es decir, uno puede canalizarse en un ciclo while; el comando read command toma una línea de su stdin y la asigna a la variable $line . $line se convierte en el comando ejecutado dentro del ciclo; y continúa hasta que no haya más líneas en su entrada.

Esto aún no funcionará con algunas estructuras de control (como otro ciclo), pero se ajusta a la ley en este caso.



El comando eval existe para este mismo propósito.

eval "$( ls | sed... )"

Más del manual de bash :

eval

eval [arguments]

Los argumentos se combinan en un solo comando, que luego se lee y se ejecuta, y su estado de salida se devuelve como el estado de salida de eval. Si no hay argumentos o solo argumentos vacíos, el estado de retorno es cero.


Intente utilizar la sustitución de procesos , que reemplaza la salida de un comando con un archivo temporal que puede obtenerse de la siguiente manera:

source <(echo id)


Para usar la solución de mark4o en bash 3.2 (macos) se puede usar una cadena aquí en lugar de tuberías como en este ejemplo:

. /dev/stdin <<< "$(grep ''^alias'' ~/.profile)"


Wow, sé que esta es una vieja pregunta, pero recientemente me encontré con el mismo problema (así es como llegué aquí).

De todos modos, no me gusta la respuesta source /dev/stdin , pero creo que encontré una mejor. Es engañosamente simple en realidad:

echo ls -la | xargs xargs

Bonito, ¿verdad? En realidad, esto todavía no hace lo que quieres, porque si tienes varias líneas las combinará en un único comando en lugar de ejecutar cada comando por separado. Entonces la solución que encontré es:

ls | ... | xargs -L 1 xargs

la opción -L 1 significa que utiliza (como máximo) 1 línea por ejecución de comando. Nota: si su línea termina con un espacio final, se concatenará con la siguiente línea. Por lo tanto, asegúrese de que cada línea termine con un espacio no espacial.

Finalmente, puedes hacer

ls | ... | xargs -L 1 xargs -t

para ver qué comandos se ejecutan (-t es detallado).

Espero que alguien lea esto!


$ ls | sed ... | source /dev/stdin

ACTUALIZACIÓN: Esto funciona en bash 4.0, así como tcsh y guión (si cambia de source a . ). Aparentemente esto fue un error en bash 3.2. De las notas de la versión de bash 4.0 :

Se corrigió un error que causaba `. '' para no leer y ejecutar comandos de archivos no regulares, como dispositivos o conductos con nombre.


`ls | sed ...`

En cierto modo me siento como ls | sed ... | source - ls | sed ... | source - ls | sed ... | source - sería más bonito, pero desafortunadamente la source no lo entiende - para decir stdin .