2012-01-05 12 views
5

È possibile ottenere l'output di un comando, ad esempio , per scrivere ogni riga di output su una sola riga?Appare l'output del comando sulla riga singola

Esempio Utilizzo:

tar -options -f dest source | [insert trickery here] 

e l'uscita mostrerebbe ogni file in elaborazione senza movimento schermo: ogni uscita sovrascrive l'ultimo. Può essere fatto?


Edit: ci sembra di avere una risposta di lavoro, ma permette di prendere ulteriormente: ne dite di fare lo stesso, ma più di 5 righe? Si vede un'uscita a scorrimento che non influisce sul resto del terminale. Penso di avere una risposta, ma mi piacerebbe vedere cosa ne pensate voi ragazzi.

+0

Hai ottenuto la modifica. Era divertente. – Dave

risposta

6

Sostituire il ritorno a capo con i ritorni a capo.

tar -options -f dest source | cut -b1-$(tput cols) | sed -u 'i\\o033[2K' | stdbuf -o0 tr '\n' '\r'; echo 

Spiegazione:

  • cut -b1-$(tput cols): tronca l'output di catrame se è più lungo del terminale è ampia. A seconda di quanto poco vuoi che il tuo terminale si muova, non è strettamente necessario.

  • sed -u 'i\\o033[2K': inserisce una riga vuota all'inizio di ogni riga. L'opzione -u per sed la mette in modalità unbuffered. stdbuf -oL sed 'i\\033[2K' funzionerebbe allo stesso modo.

  • stdbuf -o0 tr '\n' '\r': Utilizza tr per scambiare newline con ritorni a capo. Stdbuf si assicura che l'uscita sia unbuffered; senza lo \n, su un terminale con buffer di linea, non vedremmo alcun output.

  • echo: restituisce una fine riga finale, in modo che il prompt del terminale non diventi la riga finale.

Per il problema tua modifica propone:

x=0; 
echo -e '\e[s'; 
tar -options -f dest source | while read line; do 
     echo -en "\e[u" 
     if [ $x gt 0 ]; then echo -en "\e["$x"B"; fi; 
     echo -en "\e[2K" 
     echo -n $line | cut -b1-$(tput cols); 
     let "x = ($x+1)%5"; 
done; echo; 

Sentitevi liberi di Smush tutto ciò che in una sola riga. Questo in realtà si ottiene una soluzione alternativa per il problema originale:

echo -e '\e[s'; tar -options -f dest source | while read line; do echo -en "\e[u\e2K"; echo -n $line | cut -b1-$(tput cols); done; echo 

che si basa ordinatamente su nulla se non i codici VT100.

+2

Oppure con ritorni a capo, causando la sovrascrittura della riga successiva: 'tr '\ 012' '\ 015'' – tripleee

+1

Penso che si desideri stampare una nuova riga alla fine in modo che quando finisce non rovini il prompt . – mrj

+1

Non penso che questo sia ciò che l'OP sta cercando. Vuole qualche tipo di trucco con caratteri di controllo (con i backspaces o qualcosa del genere) in modo che l'output sia tutto scritto nello _same spot_. –

3

Grazie a Dave/tripleee per il cuore meccanico (sostituendo a capo con ritorni a capo), ecco una versione che funziona davvero:

tar [opts] [args] | perl -e '$| = 1; while (<>) { s/\n/\r/; print; } print "\n"' 

Impostazione $| cause Perl per filo automaticamente dopo ogni print, invece di aspettare newline, e il newline finale mantiene l'ultima linea di output da essere (parzialmente) sovrascritta quando il comando finisce e bash stampa un prompt. (È davvero brutto se è parziale, con prompt e cursore seguiti dal resto della riga di output.

Sarebbe bello farlo con tr, ma non sono a conoscenza di come forzare lo standard tr (o qualcosa di simile) per svuotare lo stdout.

Modifica: la versione precedente è effettivamente brutta, dal momento che non cancella il resto della riga dopo che cosa è stato prodotto. Ciò significa che le linee più corte che seguono linee più lunghe hanno il testo finale rimanente. Questo (certamente brutto) correzioni:

tar [opts] [args] | perl -e '$| = 1; $f = "%-" . `tput cols` . "s\r"; $f =~ s/\n//; while (<>) {s/\n//; printf $f, $_;} print "\n"' 

(Si può anche ottenere la larghezza del terminale in più modi perl-y, as described here; non volevo dipendere da moduli CPAN se

+0

Non piace neanche a questo metodo.Il pipe viene ignorato per qualsiasi ragione. Inoltre, Perl funzionerà per tutti o deve essere installato prima? – CJxD

+0

Non funziona neanche con 'cp'. 'cp' non si lamenta, ma non fa quello che dovrebbe. Nether fa la risposta precedente. = [ – CJxD

+0

@ CGJxD: ho provato questo. Funziona assolutamente per me su Ubuntu. Sei forse su una piattaforma diversa, dove 'tar' invia il suo output a stderr invece di stdout? In tal caso, dovrai aggiungere '2> & 1' prima della pipe, per reindirizzare lo stderr allo stdout in modo che il pipe lo catturi. – mrj

4
tar -options -f dest source | cut -b1-$(tput cols) | perl -ne 's/^/\e[2K/; s/\n/\r/; print' ;echo 
.

Spiegazioni:

  • | cut -b1-$(tput cols) Ciò al fine di assicurarsi che le colonne non sono troppo larghi
  • (in -ne perl) 01.Questo codice cancella la riga corrente, cancellando le linee "vecchie". Questo dovrebbe essere all'inizio della linea, al fine di garantire che la linea finale di output sia preservata e anche per garantire che non eliminiamo una riga finché non è disponibile la riga successiva.
  • (in perl -ne) s/\n/\r/ Il comando tr può essere utilizzato qui, ovviamente. Ma una volta che ho iniziato ad usare Perl, ho attaccato con esso

PS Per chiarire: Ci sono due problemi distinti 'line-width'. Entrambi devono essere risolti. (1) Abbiamo bisogno di cancellare le linee, in modo che una linea breve non sia confusa con linee più vecchie e più lunghe. (2) Se una linea è molto lunga, ed è più larga della larghezza del terminale corrente, è necessario ridurla.

+0

+1 - molto più pulito del mio! – mrj

+0

Se fosse alla fine della linea, non ci sarebbe uscita; Ogni riga che stampa, dovrebbe immediatamente cancellare – Dave

+0

@Dave, ho aggiornato il funzionamento un po '. Va bene: è all'inizio per ".. assicurarci di non eliminare una riga fino a quando non sarà disponibile la riga successiva". –

Problemi correlati