Saída do conteúdo do arquivo enquanto ele muda

44

Eu quero produzir o conteúdo de um arquivo enquanto ele é alterado, por exemplo, se eu tiver o arquivo foobar e eu fizer isso:

magic_command foobar

O terminal atual deve exibir o conteúdo do arquivo e aguardar até que, não sei, eu pressione ^ C.

Então se de outro terminal eu fizer:

echo asdf >> foobar

O primeiro terminal deve exibir a linha recém-adicionada, além do conteúdo original do arquivo (claro, dado que eu não pressionei ^ C).

Vou marcar isso como lição de casa, já que quero explorar e aprender linux, mas não é tarefa de casa, é apenas uma curiosidade minha.

    
por Paul 16.08.2012 / 16:29

5 respostas

68

Você pode usar tail command com -f :

tail -f /var/log/syslog 

É uma boa solução para o show em tempo real.

    
por 16.08.2012 / 16:34
16

Se você deseja mostrar um arquivo curto, que cabe em uma tela do terminal, e o que está mudando é possivelmente o arquivo inteiro, você poderia usar watch :

watch cat example.txt

Every 2.0s: cat example.txt                                Sun Aug  3 15:25:20 2014

Some text
another line

Ele mostra o arquivo inteiro a cada 2 segundos por padrão, incluindo um cabeçalho opcional:

A opção -d ( --differences ) destacará as alterações da versão anterior da saída ou da primeira versão.

    
por 03.08.2014 / 15:27
9

Quando preciso detectar alterações no arquivo e fazer algo diferente do que o tail -f filename , usei inotifywait em um script para detectar a alteração e agir de acordo com ela. Um exemplo de uso é mostrado abaixo. Veja man inotifywait para outros nomes e opções de eventos. Você pode precisar instalar o pacote inotify-tools , por exemplo, via sudo apt-get install inotify-tools .

Aqui está o script de exemplo, chamado exec-on-change :

 #!/bin/sh

# Detect when file named by param $1 changes.
# When it changes, do command specified by other params.

F=$1
shift
P="$*"

# Result of inotifywait is put in S so it doesn't echo
while  S=$(inotifywait -eMODIFY $F 2>/dev/null)
do
  # Remove printf if timestamps not wanted 
  printf "At %s: \n" "$(date)"
  $P
done

Em dois consoles, digitei os comandos da seguinte maneira (onde A > significa entrada no console A e B > significa entrada no console B).

A> rm t; touch t
B> ./exec-on-change t wc t
A> date >>t
A> date -R >>t
A> date -Ru >>t
A> cat t; rm t

A seguinte saída de cat t apareceu no console A:

Thu Aug 16 11:57:01 MDT 2012
Thu, 16 Aug 2012 11:57:04 -0600
Thu, 16 Aug 2012 17:57:07 +0000

A seguinte saída de exec-on-change apareceu no console B:

At Thu Aug 16 11:57:01 MDT 2012: 
 1  6 29 t
At Thu Aug 16 11:57:04 MDT 2012: 
 2 12 61 t
At Thu Aug 16 11:57:07 MDT 2012: 
 3 18 93 t

O script exec-on-change foi finalizado quando eu rm 'd t .

    
por 16.08.2012 / 20:09
6

less tem um modo de acompanhamento semelhante a tail -f - basta acessar F quando você tiver aberto.

    
por 25.09.2013 / 22:50
3

Eu tenho três soluções:

1) tail -f é uma boa ideia

2) também temos tailf para usar

3) o terceiro é um script bash:

#!/bin/bash

GAP=10     #How long to wait
LOGFILE=$1 #File to log to

if [ "$#" -ne "1" ]; then
    echo "USAGE: 'basename $0' <file with absolute path>"
    exit 1
fi


#Get current long of the file
len='wc -l $LOGFILE | awk '{ print $1 }''
echo "Current size is $len lines."

while :
do
    if [ -N $LOGFILE ]; then
        echo "'date': New Entries in $LOGFILE: "
        newlen='wc -l $LOGFILE | awk ' { print $1 }''
        newlines='expr $newlen - $len'
        tail -$newlines $LOGFILE
        len=$newlen
    fi
sleep $GAP
done
exit 0
    
por 04.03.2014 / 05:56