2014-01-15 2 views
0

Я работаю над сценарием резервного копирования, и у меня есть проблема. Я хотел бы сделать резервную копию моих документов на ftp-сервере. Потому что мне не нравятся encfs, поэтому я пытаюсь понять это, используя z-zip и зашифрованные архивы. Это работает хорошо, но я хотел бы создать новый архив только тогда, когда файл внутри подкаталога изменился, поэтому lftp только загружает измененные.Проверьте, изменился ли каталог

Мой codesnippet выглядит следующим образом:

cd /mnt/HD_a2/documents 
for i in */ 
do 7za a -t7z /mnt/HD_a2/encrypted/ul_doc/"${i%/}.7z" -p1234 -mhe "$i" 
done 

Как я могу изменить этот код, так что это только создание нового архива, если файл внутри «я» был изменен в течение последних 7 дней? (Этот сценарий выполняется хрон каждые 7 дней)

ответ

0

Так, Barmar`s answer почти правильно, но это не правильно подсчитывать файлы. Я искал другие подобные вопросы, и кажется, что это распространенная ошибка (, пожалуйста, обратите внимание, что это не важно для его решения, но это может смутить других программистов, если они касаются этого, потому что это не то, что большинство людей будет ожидайте), никто не учитывает тот факт, что имена файлов могут содержать символы новой строки. Итак, вот немного лучшая версия, которая дает вам правильное количество файлов:

for i in */ 
do 
    fileCount=$(find "$i" -type f -mtime -8 -exec printf . \;) 
    if ((${#fileCount} > 0)); then 
     7za a -t7z /mnt/HD_a2/encrypted/ul_doc/"${i%/}.7z" -p1234 -mhe "$i" 
    fi 
done 

Но что, если у вас тысячи файлов? Это создаст строку, которая точно равна количеству ваших файлов.

Таким образом, мы можем использовать это:

for i in */ 
do 
    fileCount=$(find "$i" -type f -mtime -8 -exec printf . \; | wc -c) 
    if ((fileCount > 0)); then 
     7za a -t7z /mnt/HD_a2/encrypted/ul_doc/"${i%/}.7z" -p1234 -mhe "$i" 
    fi 
done 

Или это:

for i in */ 
do 
    fileCount=$(find "$i" -type f -mtime -8 -exec echo \; | wc -l) 
    if ((fileCount > 0)); then 
     7za a -t7z /mnt/HD_a2/encrypted/ul_doc/"${i%/}.7z" -p1234 -mhe "$i" 
    fi 
done 

Надеясь, что бесполезно строка данных не будет кэшировать.

Но нам нужно только знать, есть ли НА МЕНЬШИЙ один файл, мы не должны их считать! Таким образом, мы можем немедленно остановиться, если что-то найдено.

for i in */ 
do 
    fileFound=$(find "$i" -type f -mtime -8 | head -n 1) 
    if [[ $fileFound ]]; then 
     7za a -t7z /mnt/HD_a2/encrypted/ul_doc/"${i%/}.7z" -p1234 -mhe "$i" 
    fi 
done 

Всё. Это решение будет работать МНОГО быстрее, потому что ему не нужно искать другие файлы, и даже не нужно проверять их mtime. Попробуйте запустить этот код без head, и вы заметите существенную разницу - от нескольких часов до менее секунды для моей домашней папки. (Я даже не уверен, что когда-нибудь удастся закончить его на моем компьютере, у меня есть миллионы небольших файлов в моей домашней папке ...)

+0

Зачем вам правильно подсчитывать файлы? Все, что имеет значение, равно нулю или не равно нулю. – Barmar

+0

@ Бармар Вы действительно читали мой ответ до конца? Да, но многие программисты могут вслепую предположить, что '' wc -l'' даст им правильное количество файлов, поэтому я хотел уточнить это (и вы редко увидите это правильное решение для подсчета файлов). Позже, в конце моего ответа, я дал еще лучшее решение, чтобы увидеть, есть ли хотя бы один файл. –

+0

К счастью 'find' не буферизует свой вывод, или это решение все еще будет проверять множество файлов перед выходом. – Barmar

2
for i in */ 
do 
    if [ `find "$i" -type f -mtime -7 | wc -l` -gt 0 ] 
    then 7za a -t7z /mnt/HD_a2/encrypted/ul_doc/"${i%/}.7z" -p1234 -mhe "$i" 
    fi 
done 
+0

Как насчет файлов с символами перевода строки? –

+1

Это будет работать на них. Он не использует имена файлов, он просто проверяет, содержит ли 'find' имена файлов. – Barmar

+0

Точно, но он все еще очень неэффективен, потому что он должен проверять '' mtime'' всех файлов. См. Мой ответ для лучшего решения –

Смежные вопросы