簡體   English   中英

bash腳本來查看文件夾

[英]bash script to watch a folder

我有以下情況:

有一個已安裝在Linux機器上的Windows文件夾。 在這個Windows掛載中可能有多個文件夾(手動設置)。 我必須做一些事情(最好是一個開頭的腳本)來觀看這些文件夾。

以下是步驟:監視任何傳入的文件。 確保它們完全轉移。 將其移動到另一個文件夾。 我對Windows機器上的文件傳輸程序沒有任何控制權。 我相信這是一個安全的FTP。 所以我不能要求該過程向我發送預告片文件以確保完成文件傳輸。

我寫了一個bash腳本。 我想知道這種方法可能存在的任何陷阱。 原因是,有可能為這樣的多個目錄運行此腳本的多個副本。

目前,可能需要監控多達100個目錄。

以下是腳本。 我很抱歉在這里貼了很長一段時間。 請花點時間仔細閱讀並評論/批評它。 :-)

它需要3個參數,必須要監視的文件夾,文件必須移動的文件夾,以及時間間隔,這已在下面說明。

對不起,對齊似乎有問題。 Markdown似乎不喜歡它。 我試圖正確組織它,但不能這樣做。

Linux servername 2.6.9-42.ELsmp #1 SMP Wed Jul 12 23:27:17 EDT 2006 i686 i686 i386 GNU/Linux

#!/bin/bash
log_this()
{
    message="$1"
    now=`date "+%D-%T"`
    echo $$": "$now ": " $message
}
usage()
{
    cat << EOF
Usage: $0 <Directory to be watched> <Directory to transfer> <time interval>
Time interval is the amount of time after which the modification time of a
file will be monitored. 
EOF
    `exit 1`
}

if [ $# -lt 2 ]
then
    usage
fi

WATCH_DIR=$1
APP_DIR=$2

if [ ! -d "$WATCH_DIR" ]
then
    log_this "FATAL: WATCH_DIR, $WATCH_DIR does not exist. Exiting"
    exit 1
fi

if [ ! -d "$APP_DIR" ]
then
    log_this "APP_DIR: $APP_DIR does not exist. Exiting"
    exit 1
fi


# This needs to be set after considering the rate of file transfer.
# Represents the seconds elapsed after the last modification to the file.
# If not supplied as parameter, defaults to 3.

seconds_between_mods=$3

if ! [[ "$seconds_between_mods" =~ ^[0-9]+$ ]]; then
        if [ ${#seconds_between_mods} -eq 0 ]; then
                log_this "No value supplied for elapse time. Defaulting to 3."
                seconds_between_mods=3
        else
                log_this "Invalid value provided for elapse time"
                exit 1
        fi
fi

log_this "Start Monitor."

while true
do
        ls -1 $WATCH_DIR | while read file_name
        do
            log_this "Start Monitoring for $file_name"

            # Refer only the modification with reference to the mount folder.
            # If there is a diff in time between servers, we are in trouble.

            token_file=$WATCH_DIR/foo.$$
            current_time=`touch $token_file && stat -c "%Y" $token_file`
            rm -f $token_file 2>/dev/null

            log_this "Current Time: $current_time"
            last_mod_time=`stat -c "%Y" $WATCH_DIR/$file_name`

            elapsed_time=`expr $current_time - $last_mod_time`
            log_this "Elapsed time ==> $elapsed_time"

            if [ $elapsed_time -ge $seconds_between_mods ]
            then
                    log_this "Moving $file_name to $APP_DIR"

                    # In case if there is no space left on the target mount, hide the     file
                    # in the mount itself and remove the incomplete file from APP_DIR.
                    mv $WATCH_DIR/$file_name $APP_DIR
                    if [ $? -ne 0 ]
                    then
                            log_this "FATAL: mv failed!! Hiding $file_name"
                            rm $APP_DIR/$file_name
                            mv $WATCH_DIR/$file_name $WATCH_DIR/.$file_name
                            log_this "Removed $APP_DIR/$file_name. Look for $WATCH_DIR/.$file_name and submit later."
                    fi

                    log_this "End Monitoring for $file_name"
            else
                    log_this "$file_name: Transfer seems to be in progress"
            fi
    done
    log_this "Nothing more to monitor."
    echo
    sleep 5
done

這在任何時間都不會起作用。 在生產中,您將遇到網絡問題和其他錯誤,這些錯誤可能會在上載目錄中留下部分文件。 我也不喜歡“預告片”文件的想法。 通常的方法是以臨時名稱上傳文件,然后在上載完成后重命名。

這樣,您只需列出目錄,過濾臨時名稱,如果還有任何內容,請使用它。

如果您無法進行此更改,請向您的老板尋求書面許可,以實施可能導致任意數據損壞的內容。 這有兩個目的:1)讓他們明白這是一個真正的問題而不是你構成的東西,2)在它破裂時保護自己......因為它會猜測誰會得到所有的責任?

我相信一個更加理智的方法是使用內核級文件系統通知項。 inotify 這里獲取工具。

incron是一個“inotify cron”系統。 它由一個守護進程和一個表操縱器組成。 您可以使用與常規cron類似的方式。 不同之處在於inotify cron處理文件系統事件而不是時間段。

首先確保安裝了inotify-tools

然后像這樣使用它們:

logOfChanges="/tmp/changes.log.csv" # Set your file name here.

# Lock and load
inotifywait -mrcq $DIR > "$logOfChanges" & # monitor, recursively, output CSV, be quiet.
IN_PID=$$

# Do your stuff here
...

# Kill and analyze
kill $IN_PID
cat "$logOfChanges" | while read entry; do
   # Split your CSV, but beware that file names may contain spaces too.
   # Just look up how to parse CSV with bash. :)
   path=... 
   event=...
   ...  # Other stuff like time stamps
   # Depending on the event…
   case "$event" in
     SOME_EVENT) myHandlingCode path ;;
     ...
     *) myDefaultHandlingCode path ;;
done

或者,在inotifywait上使用--format而不是-c將是一個想法。

只需要man inotifywaitman inotifywatch更多信息。

老實說,設置為在啟動時運行的python應用程序將快速有效地執行此操作。 Python具有驚人的操作系統支持,而且相當完整。

運行腳本可能會起作用,但是要小心和管理會很麻煩。 我認為你會把這些作為頻繁的cron工作來運行嗎?

為了讓你站起來,這是我寫的一個小應用程序,它采用路徑並查看jpeg文件的二進制輸出。 我從來沒有完成它,但它會讓你開始,看到python的結構以及一些使用os ..

我不會花太多時間擔心我的代碼。

import time, os, sys

#analyze() takes in a path and moves into the output_files folder, to then analyze files

def analyze(path):
    list_outputfiles = os.listdir(path + "/output_files")
    print list_outputfiles
    for i in range(len(list_outputfiles)):
        #print list_outputfiles[i]
        f = open(list_outputfiles[i], 'r')
        f.readlines()

#txtmaker reads the media file and writes its binary contents to a text file.

def txtmaker(c_file): 
    print c_file
    os.system("cat" + " " + c_file + ">" + " " + c_file +".txt")
    os.system("mv *.txt output_files")

#parser() takes in the inputed path, reads and lists all files, creates a directory, then calls txtmaker.

def parser(path):
    os.chdir(path)
    os.mkdir(path + "/output_files", 0777)
    list_files = os.listdir(path)
    for i in range(len(list_files)):
        if os.path.isdir(list_files[i]) == True:
            print (list_files[i], "is a directory")
        else:
            txtmaker(list_files[i])
    analyze(path)

def main():
    path = raw_input("Enter the full path to the media: ")
    parser(path)


if __name__ == '__main__':

    main()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM