2012-09-27 24 views
67

tengo el siguiente en Bash (en Linux)Cómo mostrar y actualizar eco en la misma línea

for dir in Movies/* 
do 
    (cd "$dir" && pwd|cut -d \/ -f5|tr -s '\n' ', ' >> ../../movielist && 
    exiftool * -t -s3 -ImageSize -FileType|tr -s '\t' ',' >> ../../movielist) 
echo "Movie $movies - $dir ADDED!" 
let movies=movies+1 
done 

Pero deseo que sea lo que el "eco" muestra la siguiente eco en la línea siguiente (No concatenar con la última salida de eco, pero reemplácela) para que parezca que se está actualizando. Similar a cómo una barra de progreso con porcentaje se mostraría en la misma línea.

Respuesta

115

Bueno, no leí correctamente la página man echo para esto.

echo tenía 2 opciones que podrían hacer esto si agregué un tercer carácter de escape.

Las 2 opciones son -n y -e.

-n no generará la nueva línea final. Entonces eso me ahorra ir a una nueva línea cada vez que hago eco de algo.

-e me permitirán interpretar los símbolos de escape de la barra invertida.

Adivina qué símbolo de escape quiero usar para esto: \r. Sí, el retorno de carro me devolvería al inicio y parecerá que estoy actualizando en la misma línea.

Así, la línea de eco se vería así:

echo -ne "Movie $movies - $dir ADDED!"\\r

que tenía que escapar el símbolo de escape para Bash no mataría a ella. es por eso que ve 2 símbolos 2 \ allí.

Según lo mencionado por William, printf también puede hacer tareas similares (y aún más amplias) como esta.

+8

Solo una nota para el futuro: printf hará exactamente lo mismo, sin ninguna opción. La ventaja es que printf generalmente se comporta de manera similar en todos los entornos y sistemas operativos, mientras que el eco a veces se puede comportar de manera muy diferente. Para scripts multiplataforma (o si crees que alguna vez te preocupes por eso), usar printf es la mejor práctica. –

+0

Impresionante @WilliamTFroggard gracias amigo. –

+3

'printf a; printf b' outputs 'ab' ---' printf a \\ r; printf b' salidas 'b' ---' printf a \\ r; dormir 1; printf b' produce 'a', luego' b' – XavierStuvw

50

Si he entendido bien, se puede lograr que la sustitución de su eco con la siguiente línea:

echo -ne "Movie $movies - $dir ADDED! \033[0K\r" 

Aquí hay un pequeño ejemplo que se puede ejecutar a entender su comportamiento:

#!/bin/bash 
for pc in $(seq 1 100); do 
    echo -ne "$pc%\033[0K\r" 
    sleep 1 
done 
echo 
+0

Parece que en zsh la 'K' no es necesaria y de hecho se saca como la letra K. – mknaf

+1

Gran ejemplo - para mí el hash bang al principio era la clave –

9

El resto de las respuestas son bastante buenas, pero solo quería agregar algo de información adicional en caso de que alguien venga aquí buscando una solución para reemplazar/actualizar un eco multilínea.

Así que me gustaría compartir un ejemplo con todos ustedes. El siguiente script fue probado en un sistema CentOS y usa el comando "timedatectl" que básicamente imprime información de tiempo detallada de su sistema.

decidí usar ese comando, ya que está de salida contiene varias líneas y funciona perfectamente para el siguiente ejemplo:

#!/bin/bash 
while true; do 
    COMMAND=$(timedatectl) #Save command result in a var. 
    echo "$COMMAND" #Print command result, including new lines. 

    sleep 3 #Keep above's output on screen during 3 seconds before clearing it 

    #Following code clears previously printed lines 
    LINES=$(echo "$COMMAND" | wc -l) #Calculate number of lines for the output previously printed 
    for ((i=1; i <= $(($LINES)); i++));do #For each line printed as a result of "timedatectl" 
    tput cuu1 #Move cursor up by one line 
    tput el #Clear the line 
    done 

done 

Lo anterior se imprimirá el resultado de "timedatectl" para siempre y sustituirá el eco anterior con información actualizada resultados.

Debo mencionar que este código es solo un ejemplo, pero quizás no la mejor solución para usted según sus necesidades. Un comando similar que haría casi lo mismo (al menos visualmente) es "watch -n 3 timedatectl".

Pero esa es una historia diferente. :)

Espero que ayude!

+1

Probado. Pasar. Gracias – XavierStuvw

1

Mi forma favorita se llama hacer el sueño a 50. aquí i variable se debe utilizar dentro de las instrucciones de eco.

for i in $(seq 1 50); do 
    echo -ne "$i%\033[0K\r" 
    sleep 50 
done 
echo "ended" 
0

Esto es útil, pruébalo y cámbialo si es necesario.

#! bin/bash 
for load in $(seq 1 100); do 
    echo -ne "$load % downloded ...\r" 
    sleep 1 
done 
echo "100" 
echo "Loaded ..." 
Cuestiones relacionadas