Изменения папки дорожки/изменения Dropbox

Сначала я знаю pyinotify.

То, что я хочу, - это загрузка на мой домашний сервер с помощью Dropbox.

У меня будет общая папка Dropbox на моем домашнем сервере. Каждый раз, когда кто-то другой, который делится этой папкой, помещает что-либо в эту папку, я хочу, чтобы мой домашний сервер подождал, пока он будет полностью загружен, и переместите все файлы в другую папку и удалите эти файлы из папки Dropbox, тем самым, сохраните Dropbox пространство.

Дело в том, что я не могу просто отслеживать изменения в папке и сразу же перемещать файлы, потому что, если кто-то загружает большой файл, Dropbox уже начнет загрузку и, следовательно, покажет изменения в папке на моем домашнем сервере.

Есть ли способ обхода? Возможно ли это с помощью API Dropbox?

Не пробовал сам, но версия CLI Dropbox, похоже, имеет метод filestatus для проверки состояния текущего файла. Отчитывается, когда сам пробовал.

Ответ 1

Вот версия Ruby, которая не ждет, пока Dropbox не будет работать, поэтому может фактически начать перемещать файлы, пока он все еще синхронизируется. Также он игнорирует . и ... Он фактически проверяет filestatus каждого файла в пределах заданного каталога.

Тогда я запустил бы этот script либо в виде cronjob, либо в отдельном экране.

directory = "path/to/dir"
destination = "location/to/move/to"

Dir.foreach(directory) do |item|
    next if item == '.' or item == '..'
    fileStatus = `~/bin/dropbox.py filestatus #{directory + "/" + item}`
    puts "processing " + item
    if (fileStatus.include? "up to date")
        puts item + " is up to date, starting to move file now."
        # cp command here. Something along this line: `cp #{directory + "/" + item + destination}`
        # rm command here. Probably you want to confirm that all copied files are correct by comparing md5 or something similar.
    else
        puts item + " is not up to date, moving on to next file."
    end
end

Это полный script, я закончил с:

# runs in Ruby 1.8.x (ftools)

require 'ftools'

directory = "path/to/dir"
destination = "location/to/move/to"

Dir.glob(directory+"/**/*") do |item|
    next if item == '.' or item == '..'
    fileStatus = `~/bin/dropbox.py filestatus #{item}`
    puts "processing " + item
    puts "filestatus: " + fileStatus
    if (fileStatus.include? "up to date")
        puts item.split('/',2)[1] + " is up to date, starting to move file now."
        `cp -r #{item + " " + destination + "/" + item.split('/',2)[1]}`

        # remove file in Dropbox folder, if current item is not a directory and 
        # copied file is identical.
        if (!File.directory?(item) && File.cmp(item, destination + "/" + item.split('/',2)[1]).to_s)
            puts "remove " + item
            `rm -rf #{item}`
        end
    else
        puts item + " is not up to date, moving to next file."
    end
end

Ответ 2

Существует клиент CLI Dropbox для Python, как вы упомянули в своем вопросе. Он возвращает "Idle...", когда он не активно обрабатывает файлы. Самый простой механизм, который я могу себе представить для достижения того, что вы хотите, - это цикл while, который проверял вывод dropbox.py filestatus /home/directory/to/watch и выполнял scp содержимого, а затем удалял содержимое, если это произошло. Потом спал пять минут или около того.

Что-то вроде:

import time
from subprocess import check_call, check_output
DIR = "/directory/to/watch/"
REMOTE_DIR = "[email protected]_server.com:/folder"

While True:
    if check_output(["dropbox.py", "status", DIR]) == "\nIdle...":
        if check_call(["scp", "-r", DIR + "*", REMOTE_DIR]):
            check_call(["rm", "-rf", DIR + "*"])
    time.sleep(360)

Конечно, я был бы очень осторожен, тестируя что-то вроде этого, помещал неправильную вещь в этот второй check_call, и вы могли потерять свою файловую систему.

Ответ 3

Вы можете запустить incrond и дождаться событий IN_CLOSE_WRITE в папке Dropbox. Тогда это будет срабатывать только после завершения передачи файла.