web-dev-qa-db-ja.com

変更中にファイルの内容を出力する

たとえば、ファイルfoobarがあり、次のような場合、ファイルの内容が変更されている間に出力したいと思います。

magic_command foobar

現在のターミナルにはファイルの内容が表示され、waitが表示されます。わからない場合は、^ Cを押します。

次に、別の端末から私が行う場合:

echo asdf >> foobar

最初のターミナルには、元のファイルの内容に加えて、新しく追加された行が表示されます(もちろん、^ Cを押さなかった場合)。

50
Paul

tail command-fを併用できます。

tail -f /var/log/syslog 

リアルタイムのショーに最適なソリューションです。

83
PersianGulf

1つの端末画面に収まる短いファイルを表示する場合、変更されるのはファイル全体である可能性があるため、watchを使用できます。

watch cat example.txt

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

Some text
another line

デフォルトでは、オプションのヘッダーを含めて、ファイル全体が2秒ごとに表示されます。

オプション -d--differences)は、前のバージョンの出力または最初のバージョンからの変更を強調表示します。

19
Volker Siegel

lessのフォローモードはtail -fに似ています-開いているときにFを押すだけです。

10
peterph

ファイルの変更を検出し、tail -f filename以外のことを行う必要がある場合は、スクリプトでinotifywaitを使用して変更を検出し、それに基づいて動作しました。以下に使用例を示します。その他のイベント名とスイッチについては、man inotifywaitをご覧ください。 inotify-toolsなどを介してSudo apt-get install inotify-toolsパッケージをインストールする必要がある場合があります。

次に、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

2つのコンソールで次のようにコマンドを入力しました(A>はコンソールAのエントリを意味し、B>はコンソール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

cat tからの次の出力は、コンソール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

exec-on-changeからの次の出力は、コンソール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

rmtしたときにexec-on-changeスクリプトが終了しました。

私には3つの解決策があります:

1)tail -fは良いアイデアです

2)使用するtailfもあります

3番目は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
4
MLSC