Показать полную графическую версию : [решено] Помощь с написанием Bat. Перемещение и удаление файлов и папок старше N дней.
Stanley5
03-12-2015, 17:10
Подскажите пожалуйста, как реализовать следующую задачу:
Есть сетевое хранилище. В нем куча папок. В данный момент интересуют 5 из них.
4 папки используются для сканов с мфу, то есть пользователь отсканил документ, мфу его положил в свою папку(файлы могут быть как pdf так и jpg, все зависит от того как настроили при сканировании)
В этих 4-х папка не должны оставаться файлы старше 3-х дней. Отсканировал-забрал, не забрал файл удалился.
Нужно, чтоб планировщик запускал bat файл который, из указанной папки все файлы старше трех дней переносил в другую папку, затем из этой "другой папки" удалял все файлы старше 20 дней. При этом в папке могут быть созданы не только файлы с изображениями, так же там могу создать и папку, которую в свою очередь тоже нужно сначала переместить а уже потом удалить с теме же временными рамками что и у файлов. Для этого был написан вот такой батник:
FORFILES /p "W:\Scan_Buh" /S /D -3 /C "cmd /c move @path "W:\EverybodyOld\Scan_Buh\""
:: Переносим все файлы и папки старше 3-х дней из папки Scan_Buh в папку EverybodyOld\Scan_Buh\
FORFILES /p "W:\EverybodyOld\Scan_Buh" /S /D -20 /C "cmd /c del @path /f /q"
:: Удаляем все файлы старше 20-и дней из папки Scan_Buh
FORFILES /p "W:\EverybodyOld\Scan_Buh" /S /C "cmd /c rd @path"
:: Удаляем все пустые папки
FORFILES /p "W:\Scan_Manager" /S /D -3 /C "cmd /c move @path "W:\EverybodyOld\Scan_Manager\""
:: Переносим все файлы и папки старше 3-дней из папки Scan_Manager в папку EverybodyOld\Scan_Manager\
FORFILES /p "W:\EverybodyOld\Scan_Manager" /S /D -20 /C "cmd /c del @path /f /q"
:: Удаляем все файлы старше 20-и дней из папки Scan_Manager
FORFILES /p "W:\EverybodyOld\Scan_Manager" /S /C "cmd /c rd @path"
:: Удаляем все пустые папки
Аналогично для остальных двух папок, меняется только путь к ним.
Сейчас добавилась еще одна папка. В ней идет обмен документами, а так же несколько папок с которыми работают все. Тут может быть куча самых различных фалов, папок, подпапок... Из этой папке так же нужно перемещать все файлы\папки старше n дней в другую папку, затем по истечение n дней удалять из другой папки. НО есть несколько папок (в них соответственно файлы) которые трогать не нужно. К примеру есть w:\test в ней еще папки 1,2,3,4,5,6, и просто фалы лежащие в корне(кол-во файлов и папок может быть какое угодно и с каким угодно расширением), нужно чтоб всё что старше n дней переместилось в w:\arhiv\test кроме папки и всего содержимого в папка 2, 4,5 эти папки просто должны пропускаться (у них есть имя которое не изменяется, ведется работа только внутри этих папок) а потом уже из папки w:\arhiv\test так же все что старше 20 дней удалялось и файлы и папки в том числе.
Как сделать исключение по названию папки? Чтоб при том же перемещении на определенную папку просто не обращалось внимания.
У Forfiles есть ключ /м но это маска с которой он работает и не исключает.
Все это на автомате, без каких либо запросов и ввода доп информации, задание ночью отработало и всё.
Помогите разобраться и дополнить батник, а возможно и переделать совсем и оптимизировать.
megaloman
05-12-2015, 20:54
Stanley5, У Вас целый роман при описании постановки задачи :) дополнить батник, а возможно и переделать совсем и оптимизировать.
Я бы предложил не копировать исходные файлы старше нужного числа дней как они есть, а архивировать в архив в один файл с именем - датой в формате yyyymmdd, с такими названиями файлы легко сортируются. При этом используя ключи winrar этого можно легко добиться. И, далее, удалять в архивной папке не файлы старше определённой даты (например, 20 дней), а оставлять нужное число архивов (например, 20 штук), что, в принципе, при ежедневном создании архивов, одно и то же. Получилось громоздко, но довольно универсально. Степень сжатия rar можно регулировать при необходимости экономии времени при работе ключом -m. В примере я взял -m1 (довольно быстрая работа). Еще быстрее -m0 без сжатия. Без указания работает уровень m3.
@Echo Off
CLS
rem chcp 1251 >nul
SetLocal EnableDelayedExpansion
Set "ARC=%ProgramFiles%\winrar\winrar.exe"
Set "FTmp=%Tmp%\~tmp.tmp"
Call :Arc_Copy "W:\Scan_Buh","W:\EverybodyOld\Scan_Buh",3,20
Call :Arc_Copy "E:\Delete\CMD\JS_Host","E:\Arhiv\JS_Host",3,20,No_JS_Host
Call :Arc_Copy "w:\test","w:\arhiv\test",3,20,No_test
GoTo :Eof
:Arc_Copy
rem %1 Корневая папка откуда архиваруем (с удалением исходных) файлы
rem %2 Папка куда архивируем файлы
rem %3 Архивируем файлы старше этого кол-ва дней под
rem %4 Сколько архивов храним в архивной папке
rem %5 При наличии исключений имя процедуры где формируется файл с исключениями
Call :FromNow -%3 %Date%
Md "%~2" 2>nul
Echo ------ %Date% -%3 %yyyymmdd%
If Exist "%~1" (Echo %1) Else (Echo Не найдено %1 & GoTo :Eof)
If Exist "%~2" (Echo %2) Else (Echo Не найдено %2 & GoTo :Eof)
If '%5'=='' (
"%ARC%" a -r -df -m1 -tb%yyyymmdd%0000 "%~2\%yyyymmdd%" "%~1\*.*"
) Else (
Call :%5 "%~1"
"%ARC%" a -r -df -m1 -tb%yyyymmdd%0000 -x@"%FTmp%" "%~2\%yyyymmdd%" "%~1\*.*"
Del "%FTmp%" >nul 2>nul
)
FOR /F "usebackq Skip=%4 delims=" %%i IN (`Dir "%~2\*.rar" /b /a:-d /O:-N 2^>nuL`) DO del "%~2\%%i"
GoTo :Eof
:No_JS_Host
rem %1 -корневая папка исходных файлов
rem во временный текстовый файл пишем папки (файлы) исключений
Echo>"%FTmp%" %~1\Дискета_от_книги\*.*
Echo>>"%FTmp%" %~1\Из_интернета\Основы WSH\*.*
Echo>>"%FTmp%" %~1\Отлажено\*.*
GoTo:Eof
:No_test
Echo>"%FTmp%" %~1\2\*.*
Echo>>"%FTmp%" %~1\4\*.*
Echo>>"%FTmp%" %~1\5\*.*
GoTo:Eof
:FromNow
rem Пересчет даты на заданное кол-во дней
rem Формат даты dd.mm.yyyy +- дни получим новые yyyymmdd
rem Заимствовано http://forum.oszone.net/thread-186889.html
rem вызов Call :FromNow %DeltaDay% %Date%
rem результат в перемменной %yyyymmdd%
SetLocal
Set DT=%2
Set yyyy=%DT:~-4%& set /a mm=100%DT:~3,2%%%100& set /a dd=100%DT:~,2%%%100
Set /A JD=%~1+dd-32075+1461*(yyyy+4800+(mm-14)/12)/4+367*(mm-2-(mm-14)/12*12)/12-3*((yyyy+4900+(mm-14)/12)/100)/4
Set /A L=JD+68569,N=4*L/146097,L=L-(146097*N+3)/4,I=4000*(L+1)/1461001
Set /A L=L-1461*I/4+31,J=80*L/2447,K=L-2447*J/80,L=J/11
Set /A J=J+2-12*L,I=100*(N-49)+I+L
Set /A yyyy=I,mm=100+J,dd=100+K
EndLocal& Set yyyymmdd=%yyyy%%mm:~-2%%dd:~-2%
GoTo :Eof
Процедура архивации Call :Arc_Copy вызывается для каждой архивируемой папки.
Её аргументы описаны.
При наличии исключений в аргументах этой процедуры указывается имя процедуры, где формируется текстовый файл для конкретного случая с перечислением полных имён папок (файлов) исключений.
В примере это процедуры No_JS_Host и No_test
Stanley5
07-12-2015, 15:29
Stanley5, У Вас целый роман при описании постановки задачи »
Старался как можно подробнее описать задачу)))
Спасибо за код, буду пробовать.
Есть еще один вопрос с исключениями. При наличии исключений в аргументах этой процедуры указывается имя процедуры, где формируется текстовый файл для конкретного случая с перечислением полных имён папок (файлов) исключений. »
У меня сейчас вот такая штука.... То есть по указанному пути включая все подкаталоги кроме "123" вывести на экран.
FORFILES /p "W:\Test" /S /C "cmd /c if not @path==\"W:\Test\123\" echo @path"
Не подскажете как именно тут полностью исключить 123 вместе с подкаталогами? Если убрать ключ /S то будет выведен список только из корня папки Test(все кроме 123) но подпапки уже не покажет, а с ключиком показывает все что и в папке 123, файлы там могут быть совершенно разные, как полностью исключить папку? вместе с содержимым?
FORFILES /p "W:\Test" /S /C "cmd /c if not @path==\"W:\Test\123\" echo @path"
"W:\Test\Новая папка"
"W:\Test\Лист Microsoft Excel.xlsx"
"W:\Test\папка"
"W:\Test\Новая папка (2)"
"W:\Test\Новая папка\Новая папка"
"W:\Test\123\Лист Microsoft Excel.xlsx"
"W:\Test\Новая папка (2)\Лист Microsoft Excel.xlsx"
FORFILES /p "W:\Test" /C "cmd /c if not @path==\"W:\Test\123\" echo @path"
"W:\Test\Новая папка"
"W:\Test\Лист Microsoft Excel.xlsx"
"W:\Test\папка"
"W:\Test\Новая папка (2)"
megaloman
07-12-2015, 19:52
@Echo Off
CLS
Echo>~tmp.tmp D:\Delete\123\
FOR /F "usebackq delims=" %%i IN (`xcopy "D:\Delete\*.*" /S /L /EXCLUDE:~tmp.tmp 2^>nuL`) DO echo %%i
Del ~tmp.tmp
Либо @Echo Off
CLS
SetLocal EnableExtensions EnableDelayedExpansion
FOR /F "usebackq delims=" %%i IN (`dir "D:\Delete\*.*" /S /B /A:D 2^>nuL`) DO (
Set "FName=%%i\"
If "!FName:\Delete\123\=!"=="%%i\" echo %%i
)
Либо @Echo Off
CLS
SetLocal EnableExtensions EnableDelayedExpansion
FOR /F "usebackq delims=" %%i IN (`dir "D:\Delete\*.*" /S /B 2^>nuL`) DO (
Set "FName=%%i\"
If "!FName:\Delete\123\=!"=="%%i\" echo %%i
)
Stanley5
09-12-2015, 12:20
Спасибо!!!
Shurik006
26-02-2019, 14:53
Добрый день.
Не подскажете, пожалуйста, как в команде перемещения файлов из одной директории в другую (самая первая команда автора), так же указать исключения.
Дело в том, что помимо перемещения файлов старше 3-х дней так же требуется оставить пару системных файлов в директории. Некоторые из них без расширения.
Shurik006,
например составляете список (list.txt) с именами файлов что надо оставить в покое, а остальные пускаете в работу
@echo off
set "d=C:\papka"
set "f=C:\list.txt"
for /f "delims=" %%a in ('xcopy /sl /exclude:%f% "%d%\*"') do echo Файлы не вошедшие в список исключения: "%%a"
pause& exit
Shurik006
26-02-2019, 15:43
alpap,
Правильно понимаю, что вы предоставили скрипт только исключения? (т.е. в примере нет самой команды копирования)
В исключение попадёт papka и всё, что перечислено в текст. документе?
В команде forfiles указать исключения невозможно? :)
Почему спрашиваю. Дело в том, что FORFILES имеет возможно удалять файлы старше n дней, а xcopy нет, соот-но не понятно, как теперь это всё совместить.
Спасибо за то, что отозвались.
как теперь это всё совместить »
@echo off
set "d=C:\papka"
set "f=C:\list.txt"
for /f "delims=" %%a in ('xcopy /sl /exclude:%f% "%d%"') do (
forfiles /p "%d%" /s /d -3 /c "cmd /c echo @path"|>nul find "%%a" && >nul 2>&1 del /q "%%~a")
)
pause& exit
вообще, если у вас немного файлов на исключение проще так
@echo off
set "d=C:\papka"
set "f1=C:\papka\bbb.txt"
set "f2=C:\papka\nnn.txt"
for /f "delims=" %%a in ('forfiles /p "%d%" /s /d -3 /c "cmd /c echo @path"^|findstr /v /c:"%f1%" /c:"%f2%"') do >nul 2>&1 del /q "%%~a"
pause& exit
Shurik006
26-02-2019, 19:09
alpap,
Спасибо Вам.
Не сочтите за грубость, просто решение необходимо было довольно оперативно, включил всё своё 'скриптовое обаяние', которое смог.
Поэтому пока ожидал от вас ответа, рассмотрел robocopy. Да и новичку он проще в понимании.
Необходимые файлы сделал скрытыми, а в команде указал соответствующее исключение.
Получилось так
robocopy /move /xa:h /minage:3 "D:\old" "D:\new"
Только по robocopy не могу понять пары моментов. Если не сложно, смогли бы разъяснить. Нет, эта команда уже выполняет всё необходимое, но есть нюансы.
В чистом виде переноса /move (без доп. условий) она моментально переносит большие файлы с диска на диск (=проводниковое вырезать/вставить). Как только начинаешь указывать момент со скрытыми файлами и датой (т.е. доп. условия), в командной строке сразу же видно, что бегут проценты выполнения. Т.е. она сначала копирует, затем удаляет и эта операция происходит дольше.
Сначала попробовал исключить необходимые файлы посредством установки атрибутов чтения и условия /ia:rs, но команда копирует только их, а всё остальное оставляет. Совсем не понял, где я не прав? :)
Благодарю.
она моментально переносит большие файлы с диска на диск (=проводниковое вырезать/вставить). »
1. Нет. Это ни разу не «проводниковое вырезать/вставить». Проводник работает по совсем иным принципам.
2. И с раздела на раздел перенос больших файлов никак не может работать быстро (если только у Вас не SSD или «большие файлы» в реальности легко помещаются целиком в кэш накопителя).
Т.е. она сначала копирует, затем удаляет »
Нет, не должно такого быть. exclude — это честный exclude.
Т.е. она сначала копирует, затем удаляет и эта операция происходит дольше. »
В спецификации утилиты robocopy сказано:
/MOV Moves files (that is, deletes source files after copying).
/MOVE Moves files and directories (that is, deletes source files and directories after copying).
In some situations, you may want to move files instead of copying them, especially if disk space is at a premium on your network. You can use the /MOVE switch to delete source files from the source directory tree after they have been successfully copied to the destination. /MOVE also deletes empty directories from the source directory tree.
Even with /MOVE specified, however, Robocopy deletes only those source files that it successfully copies to the destination. There is no guarantee that a skipped source file is identical to its corresponding destination file (even if the file times and sizes are identical) until immediately following a successful copy. For that reason, some files and directories (such as skipped Same files) might remain in the source tree even when /MOVE is specified. You must determine whether to delete the remaining entries, and do so manually.
Т.е. это утилита именно копирования, а удаление происходит уже после успешного копирования и никак иначе.
- Утром деньги, вечером стулья
- А можно наоборот?
- Можно, но деньги вперед!
:)
Shurik006
27-02-2019, 10:21
2. И с раздела на раздел перенос больших файлов никак не может работать быстро (если только у Вас не SSD или «большие файлы» в реальности легко помещаются целиком в кэш накопителя). »
Там по iscsi хранилище, скорость действительно очень большая, поэтому перенос даже 2Гб файла происходил быстро.
Нет, не должно такого быть. exclude — это честный exclude. »
Да, прошу прощения, я ошибся. xa работает как надо.
Т.е. это утилита именно копирования, а удаление происходит уже после успешного копирования и никак иначе. »
Да, всё понял. Спасибо.
Значит навыдумывал зачем-то :)
YuS_2, разве речь не про исключение файлов шла?
разве речь не про исключение файлов шла? »
Не совсем... там просили объяснить "пару моментов", а второй вопрос возник из первого.
Т.е. человек начал отталкиваться от этого:
В чистом виде переноса /move (без доп. условий) она моментально переносит большие файлы с диска на диск »
А это неверно, в силу принципа работы самой утилиты и то, что я процитировал из спецификации, как раз, этот принцип описывает.
Никакими ключами этот алгоритм изменить невозможно. Ну, т.е. получить чистый move, даже в пределах одного диска, не получится, именно copy, а затем delete. Просто уточнил.
А это неверно, в силу принципа работы самой утилиты »
Это неверно в силу того принципа, что это в любом случае означает чтение-запись содержимого, а не просто создание/удаление записей в разных каталогах одного и того же раздела. По каким бы принципам ни работала утилита.
Это неверно в силу того принципа, что это в любом случае означает чтение-запись содержимого »
А я что сказал? :)
Физический перенос данных в пределах одного диска не осуществляется, при выполнении операции move, а в утилите просто вводит в заблуждение схожий по названию ключ... это и имелось в виду.
Если заняться подробным описанием принципа работы файловой системы (как осуществляется перенос файлов в пределах одного диска, на разные диски, копирование, удаление, MFT таблицы и т.д.), это в пару строк не уместится, потому и не стал даже пытаться... ну, а если вдруг кому-то интересно, в интернете же можно поискать и почитать.
Добавлено:
По каким бы принципам ни работала утилита. »
А вот это, как раз, важно. Если утилита умеет переносить файлы, т.е. пересоздавать ссылки в MFT таблице, то это уже не копирование файла с последующим удалением исходных данных, а именно перенос. И Robocopy, как раз, работает по принципу: сначала копируем данные, затем удаляем их, никаких переносов/move, независимо от исходного и конечного местоположения данных, она не делает.
А я что сказал? :)»
YuS_2, вот и разобрались ;).
А вот это, как раз, важно. Если утилита умеет переносить файлы, т.е. пересоздавать ссылки в MFT таблице, то это уже не копирование файла с последующим удалением исходных данных, а именно перенос. И Robocopy, как раз, работает по принципу: сначала копируем данные, затем удаляем их, никаких переносов/move, независимо от исходного и конечного местоположения данных, она не делает. »
А я что сказал :lol: ? Даже если б умела в move — на разных разделах никак не получится.
А я что сказал ? Даже если б умела в move — на разных разделах никак не получится. »
Да-да, в этом смысле однозначно, принцип не имеет значения :)
Да-да, в этом смысле однозначно, принцип не имеет значения :)»
Так выпьем же :Beer: за понимание!
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.