Liên tục kiểm tra nếu tập tin được sửa đổi bash


8

Tôi có một tập tin gọi là file1 Tôi muốn trong một tập lệnh, bất cứ khi nào có sự thay đổi trong đó, hãy làm một cái gì đó, một tiếng bíp thực sự. Làm thế nào để làm điều đó?

Câu trả lời:


14

Nếu bạn đã inotify-toolscài đặt (ít nhất đó là tên gói trên Debian) khi bạn có thể làm một cái gì đó như thế này:

while inotifywait -q -e modify filename >/dev/null; do
    echo "filename is changed"
    # do whatever else you need to do
done

Điều này chờ sự kiện "sửa đổi" xảy ra với tệp có tên "tên tệp". Khi điều đó xảy ra, inotifywaitđầu ra lệnh filename MODIFY(mà chúng ta loại bỏ bằng cách gửi đầu ra tới / dev / null) và sau đó kết thúc, điều này làm cho phần thân của vòng lặp được nhập vào.

Đọc trang web inotifywaitđể biết thêm khả năng.


Điểm hay, tôi đã không đọc trang này rất tốt :-)
wurtel

Bạn không thực sự cần while. Cũng lưu ý rằng những gì con người coi là "sửa đổi" có thể không phải lúc nào cũng hoạt động: ví dụ, điều này sẽ bắt một phần phụ, nhưng nó sẽ không bắt được một trình soạn thảo như vim(tập tin đã xem được đổi tên hoặc hoán đổi với bản sao lưu), cũng không perl -i(tại chỗ chỉnh sửa) thay thế tệp bằng một cái mới. Một khi một trong những điều đó xảy ra, inotifywaitsẽ không bao giờ trở lại. Xem một nút và xem tên tệp không hoàn toàn giống nhau, vì vậy nó phụ thuộc vào trường hợp sử dụng.
mr.spuratic

1
Bạn có thể thêm các sự kiện khác để chờ đợi, ví dụ: move_selfsẽ bắt các đổi tên. Xem trang chủ để biết danh sách đầy đủ các sự kiện.
wurtel

2

Nếu không có inotifywait, bạn có thể sử dụng tập lệnh nhỏ này và một công việc định kỳ (mỗi phút hoặc lâu hơn):

#!/usr/bin/env bash
#
# Provides      : Check if a file is changed
# 
# Limitations   : none
# Options       : none
# Requirements  : bash, md5sum, cut
# 
# Modified      : 11|07|2014
# Author        : ItsMe
# Reply to      : n/a in public
#
# Editor        : joe
#
#####################################
#
# OK - lets work
#

# what file do we want to monitor?
# I did not include commandline options
# but its easy to catch a command line option
# and replace the defaul given here
file=/foo/bar/nattebums/bla.txt

# path to file's saved md5sum
# I did not spend much effort in naming this file
# if you ahve to test multiple files
# so just use a commandline option and use the given
# file name like: filename=$(basename "$file")
fingerprintfile=/tmp/.bla.md5savefile

# does the file exist?
if [ ! -f $file ]
    then
        echo "ERROR: $file does not exist - aborting"
    exit 1
fi

# create the md5sum from the file to check
filemd5=`md5sum $file | cut -d " " -f1`

# check the md5 and
# show an error when we check an empty file
if [ -z $filemd5 ]
    then
        echo "The file is empty - aborting"
        exit 1
    else
        # pass silent
        :
fi

# do we have allready an saved fingerprint of this file?
if [ -f $fingerprintfile ]
    then
        # yup - get the saved md5
        savedmd5=`cat $fingerprintfile`

        # check again if its empty
        if [ -z $savedmd5 ]
            then
                echo "The file is empty - aborting"
                exit 1
        fi

        #compare the saved md5 with the one we have now
        if [ "$savedmd5" = "$filemd5" ]
            then
                # pass silent
                :
            else
                echo "File has been changed"

                # this does an beep on your pc speaker (probably)
                # you get this character when you do:
                # CTRL+V CTRL+G
                # this is a bit creepy so you can use the 'beep' command
                # of your distro
                # or run some command you want to
                echo 
        fi

fi

# save the current md5
# sure you don't have to do this when the file hasn't changed
# but you know I'm lazy and it works...
echo $filemd5 > $fingerprintfile

2

Đã tìm kiếm một lót trên MacOS. Giải quyết như sau. Tổng hợp và thêm công cụ này vào đường dẫn của tôi. Điều này mất ít hơn 30 giây.

$ git clone git@github.com:sschober/kqwait.git
$ cd kqwait
$ make
$ mv kqwait ~/bin
$ chmod +x ~/bin/kqwait

Tiếp theo, tôi đã đi đến thư mục mà tôi muốn xem. Trong trường hợp này, tôi muốn xem tệp đánh dấu để thay đổi và nếu thay đổi vấn đề a make.

$ while true; do kqwait doc/my_file.md; make; done

Đó là nó.


1
như một lưu ý, đã hoạt động tốt (nếu nội dung tệp thay đổi), dường như chỉ là OS X và bạn có thể cài đặt chế độ xem brew install kqwaitvà bạn có thể chuyển nhiều tệp cho nó như thếkqwait **/*
rogerdpack

0

Bạn có thể không cần so sánh md5sum nếu bạn có sẵn tiện ích diff.

if ! diff "$file1" "$file2" >/dev/null 2>&1; then
  echo "$file1 and $file2 does not match" >&2
  ## INSERT-YOUR-COMMAND/SCRIPT-HERE
  ## e.g. cp "$file1" "$file2"
fi

các ! phủ định ví dụ true nếu tuyên bố là sai

Hãy cẩn thận là bạn cần tập tin gốc để so sánh với diff (imo) giống như tập lệnh md5sum đang làm ở trên.


Sử dụng diff -q, nếu diffhỗ trợ nó.
muru

Ok, hãy thử rằng: echo foo> foo.txt; thanh tiếng vang> bar.txt; diff foo.txt bar.txt -> Tệp foo và thanh khác nhau ## (rất nhiều cho việc khá :))
Jetchisel

1
Nó yên tĩnh hơn mọi sự khác biệt được đánh vần. -qcó nghĩa là "báo cáo nếu chỉ các tệp khác nhau", không phải chúng khác nhau như thế nào. Vì vậy, diff -qngừng so sánh thời điểm một sự khác biệt được nhìn thấy, có thể là hiệu suất rất hữu ích khôn ngoan. Xem tài liệu GNU , ví dụ. Nếu toàn bộ câu trả lời của bạn có hiệu quả bằng cách không sử dụng md5sum, thì không sử dụng diff -qnếu có sẵn sẽ đánh bại điểm đó.
muru

Ok, -q "hiệu suất khôn ngoan" là tốt nhưng nó vẫn in một cái gì đó thành thiết bị xuất chuẩn / stderr nếu tệp khác nhau. Tôi đã nêu! Tôi phủ nhận điều gì? những gì tôi đang theo là trạng thái thoát của diff không phải là 0, (Xem tài liệu GNU) sau đó thực hiện hành động.
Jetchisel

Bạn đang thiếu điểm. Tôi không có mong muốn giải thích thêm.
muru

0

Bạn có thể thử entrcông cụ dòng lệnh, vd

$ ls file1 | entr beep

entrcần phải được cài đặt hoặc ít nhất đó là trường hợp của Ubuntu. Nó nên có mặt trong hầu hết các kho lưu trữ xa ngoài kia.
rbaleksandar

0

nếu bạn đang kiểm tra các thay đổi trong repo git, bạn có thể sử dụng:

#!/usr/bin/env bash

diff="$(git diff | egrep some_file_name_or_file_path | cat)"

if [[ -n "$diff" ]] ; then
    echo "==== Found changes: ===="
    echo "diff: $diff"
    exit 1
else
    echo 'Code is not changed'
fi

0
Done in 2 steps Tested and worked fine in both scenarios

a. cp orginalfile fileneedto_be_changed'(Chỉ cần làm một lần)

orginalfile=====>which supposed to be changed

b.

differencecount=`awk 'NR==FNR{a[$0];next}!($0 in a){print $0}' orginalfile fileneedto_be_changed|wc -l`

if [ $differencecount -eq  0 ]
then
echo "NO changes in file"
else
echo "Noted there is changes in file"
fi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.