Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Архивирование каталога (http://forum.oszone.net/showthread.php?t=337525)

UserX 01-11-2018 22:08 2839012

Архивирование каталога
 
Здравствуйте!

Помогите, пожалуйста, со следующими вопросами.

1.
Есть каталог Src и каталог Dst.
Требуется создать батник, который будет запускаться периодически, т.е. от случая к случаю, и который будет добавлять архивы ВСЕХ каталогов, включая их подкаталоги, из Src в Dst с именами архивов, совпадающими с именами каталогов первого уровня из Src.
То есть, после отработки такого батника, в Dst должны создаться все несуществующие там архивы с именами, совпадающими с именами каталогов первого уровня из Src.
Архивы в Dst могут быть как *.rar, *.zip, *.7z и пр. одновременно. Важны лишь сами имена без их архивного расширения.
В целях ускорения работы такого батника при его повторных запусках, хотелось бы, чтобы при наличии в каталоге Dst архивов (*.rar, *.zip, *.7z и пр.) с именами каталогов из Src, эти каталоги из Src повторно в Dst не переархивировались.
То есть, если запустить такой батник в случае, когда в Dst уже имеются все имена архивов, совпадающие (без учёта архивного расширения типа .rar, .zip, .7z и пр.) c именами каталогов первого уровня из Src, то такой батник ничего не должен создавать или перепаковывать.
При этом должно быть допустимым наличие в Dst прочего содержимого - как файлов, так и папок, которые вообще не имеют отношения к именам из Src.

2.
Если предположить частный случай по первому вопросу - имена каталогов первого уровня в Src находятся в формате даты YYYYMMDD, хотелось бы отдельным батником установить реальные даты создания/изменения этих каталогов в соответствии с их именами. Время не важно.

Буду признателен за помощь.

Iska 02-11-2018 03:38 2839041

Чересчур дурная лабораторка.

megaloman 02-11-2018 18:25 2839128

UserX,
лабораторка?
Код:

@Echo Off
cls
        Set "Src=Z:\Box_In\Мой контент\Книги\*.*"
        Set "Dst=Z:\Книги.arc"

        Set Arc="C:\Program Files\7-Zip\7zG.exe" a -r
        Set "Ext=7Z"

        If Not Exist "%Dst%" Md "%Dst%"
        FOR /D %%d IN ("%Src%") DO (
                If Not Exist "%Dst%\%%~nxd.*" (Echo "%%d" &%Arc% "%Dst%\%%~nxd.%Ext%" "%%d\*.*")
        )
pause

Цитата:

Цитата UserX
хотелось бы отдельным батником установить реальные даты создания/изменения этих каталогов в соответствии с их именами. Время не важно. »

Моя Ваша не понимайт.
Есть, например, папка 20180925. Что должно происходить в батнике и какой результат его работы?

Iska 02-11-2018 18:33 2839133

Цитата:

Цитата megaloman
Моя Ваша не понимайт. »

Я ж говорил — лабораторка дурная :).

UserX 02-11-2018 18:58 2839138

megaloman, огромное Вам спасибо за Ваш отклик без излишней демонстрации своего превосходства над оппонентом.
Сейчас опробую Ваш батничек и отпишусь.

Цитата megaloman:
Есть, например, папка 20180925. Что должно происходить в батнике и какой результат его работы? »
Да просто эта эта папка 20180925 должна получить дату своего создания и изменения 25.09.2018, и всё. :)

Iska, и вам спасибо за то, что оказались неравнодушны. Ибо, как сказал Юлиус Фучек: "Бойся равнодушных! Это с их молчаливого согласия совершается всё зло на земле!"
Очевидно, вас бояться не следует.

Iska 02-11-2018 19:24 2839147

Цитата:

Цитата megaloman
Что значит получить? »

Это значит, что дорога лежит в PowerShell, поскольку на пакетных файлах нет средств для задания таких свойств в принципе (сторонние средства в расчёт не берём), на WSH свойства .DateCreated/.DateLastModified — только для чтения (дату последней модификации ещё можно задать посредством Shell → Folder → FolderItem.ModifyDate, но больно уж извращённый способ получается).

UserX 02-11-2018 19:45 2839149

Цитата megaloman:
Что значит получить? »
Это значит, что дата создания этой папки не совпадает с датой, определяемой именем папки. Хотелось бы это устранить и привести в соответствие.

megaloman, проверил Ваш батник.
Немного его изменил под себя и всё ПРЕВОСХОДНО сработало.
Огромное Вам спасибо!
----------------------------
@Echo Off
cls
Set "Src=C:\111\Src\*.*"
Set "Dst=C:\111\Dst"

Set Arc="C:\Program Files\WinRar\Rar.exe" a -r -ep1 -dh -m5 -s -rr5p -ts+ -y
Set "Ext=rar"

If Not Exist "%Dst%" Md "%Dst%"

FOR /D %%d IN ("%Src%") DO (
If Not Exist "%Dst%\%%~nxd.*" (Echo "%%d" &%Arc% "%Dst%\%%~nxd.%Ext%" "%%d\*.*")
)
----------------------------

Если не использовать ключ -ep1, то в архиве сохраняется весь путь C:\111\Src\Cat_name
Ключ -ep1 подавил сохранение в архиве лишнего пути, правда, несколько больше, чем хотелось бы. :)
А без этого ключа задача как-то решается?

Iska 02-11-2018 20:23 2839161

megaloman, а я понял так, что дату создания и дату последней модификации каталога надо задавать по содержащейся в его имени дате (время при этом несущественно).

UserX 02-11-2018 20:35 2839166

Цитата megaloman:
То есть, если папка 20180925 изменялась 20180929, то её надо переименовать? 20180925-->20180929 »

Не-не, вообще ничего переименовывать не нужно. Просто в результате обычного копирования были утрачены исходные даты создания папок. Но эти исходные даты создания папок являются именами этих папок.
Так что нужно взять папку с именем 20180925 и (можно даже ничего не проверяя) установить ей дату 20180925.
Соответвственно, папка с именем 20180929 должна получить дату 20180929.
То есть, после отработки, батник должен привести дату создания файла в соответствие с его именем.

Извините, пожалуйста, что не слишком понятно ставил вопрос.

megaloman 02-11-2018 20:39 2839168

Цитата:

Цитата UserX
Ключ -ep1 подавил сохранение в архиве лишнего пути, правда, несколько больше, чем хотелось бы »

UserX,
А так, Если не использовать ключ -ep1? (остальные ключи не трогал и смысл их наизусть не помню - Ваша ответственность). Но, ИМХО, m5 -это чересчур, иногда архив получается больше, чем m3, а время радикально увеличивается
Код:

@Echo Off
cls
        Set "Src=Z:\Box_In\Мой контент\Книги"
        Set "Mask=*.*"
       
        Set "Dst=Z:\Книги.arc"

        Set Arc="C:\Program Files\WinRar\WinRar.exe" a -r -dh -m5 -s -rr5p -ts+ -y
        Set "Ext=rar"


        If Not Exist "%Dst%" Md "%Dst%"
        Pushd "%Src%" &&(
                FOR /D %%d IN ("%Mask%") DO (
                        If Not Exist "%Dst%\%%~nxd.*" (Echo %%~td "%%d" &%Arc% "%Dst%\%%~nxd.%Ext%" "%%d\*.*")
                )
        Popd
        )
pause

Здесь Mask - это маска имён папок (не файлов!). Можно, например, задать 20??????.
Iska, Вы поняли, что надо изменить атрибуты файла
Цитата:

Цитата Iska
на пакетных файлах нет средств для задания таких свойств в принципе (сторонние средства в расчёт не берём »

Тогда мне не фиг ловить в рамках этого решения делать нечего.

UserX 02-11-2018 21:07 2839172

Цитата:

Цитата megaloman
А так, Если не использовать ключ -ep1? »

Всё чётко сработало как мне было и нужно! Теперь в имени архива находится и имя папки, совпадающее с именем архива, но это я вижу дополнительным преимуществом, поскольку в случае переименования архива, внутри него останется правильное исходное имя папки.

Огромное Вам спасибо! В батниках Вы не просто мегаломэн, а настоящий мегалодон! :up

Iska 02-11-2018 22:06 2839184

Цитата:

Цитата UserX
а настоящий мегалодон! »

Ещё никогда Штирлиц не был так близок к провалу :).

megaloman 02-11-2018 23:55 2839197

Iska,
Придумал достаточно идиотский способ, на вложенные файлы/папки он не действует
Код:

@Echo Off
cls
        Set "BoxIn=Z:\Box_In"
        Set "Mask=20??????."
       
        Set "TD=%Date%"
       
        FOR /D %%d IN ("%BoxIn%\%Mask%") DO Set "DD=%%~nd" &Call :ReData %%DD:~6,2%%.%%DD:~4,2%%.%%DD:~0,4%% "%%d"
        Date %TD%
pause
GoTo :Eof

:ReData
        Date %1
        Ren %2 "%~nx2.tmp" ||Exit /B 2
        Md %2 &&(
                For /F "usebackq delims=" %%i IN (`2^>nul Dir /B "%~2.tmp"`) DO (
                        Move "%~2.tmp\%%i" "%~2\" >nul
                )
                Rd "%~2.tmp"
        )
GoTo :Eof


UserX 03-11-2018 01:36 2839203

megaloman, это работает!! Вы - просто супер. :clapping:

UserX 04-11-2018 21:48 2839367

megaloman, мне невероятно понравилась Ваша идея с маской.
С такой идеей мою частную задачу (лабораторку) можно обобщить на более общую задачу.

Допустим, есть группа файлов (папок), имена которых связаны с датой их создания. Например:

<Info1>2018<delimeter>10<delimeter>??<Info2>

где
<Info1> и <Info2> (вместе с символами < и >, которые используются лишь для улучшения читабельности) - некоторые тексты, являющиеся необязательной частью имени файла. <Info1> и/или <Info2> - произвольный текст, который может и отсутствовать;
<delimiter> - символ-разделитель между годом, месяцем и днём в имени файла. Может быть не один, а может и вовсе отсутствовать;

Например, если указывается маска:
Set "Mask=File_2018-10-??_Original"
то подразумевается, что данная маска будет читаться так:
"Группа всех файлов (каталогов), начинающаяся со слова "File_" и заканчивающаяся словом "_Original" за весь октябрь месяц 2018 года.

Теперь сама задача.
Очень хотелось бы модифицировать Ваш последний скрипт, таким образом, чтобы по указанной маске из каталога Src выбирался ТОЛЬКО ОДИН самый последний по сортирумому имени файл и, если архива с таким именем нет в каталоге Dst, то он туда архивировался.

То есть из приведённой маски:
File_2018-10-??_Original
из Src должен выбраться только один файл с именем "File_2018-10-31_Original" (или другой последний, если за 31.10.2018 ничего нет) и архивироваться в Dst при отсутствии в нём архва с таким именем.

Оно, конечно, в приведённой маске указание направления сортировки с Ascending на Discending могло бы вместо последнего октябрьского файла 2018 года выбрать первый октябрьский файл 2018 года, но это уже может оказаться перебором с моей стороны.

Я извиняюсь, если вдруг подкидываемые мною "лабораторки" стали выглядеть как некоторая наглость со стороны человека, который сам только теоретизирует, а делать за него должен кто-то другой.
Ничего такого в мыслях не было. Просто подкинутая в Вашем скрипте идея маски меня совершенно свела с ума своим великолепием и очень захотелось её практически применить с максимальной эффективностью.

megaloman 04-11-2018 22:48 2839372

Код:

@Echo Off
cls
        Set "Src=Z:\Box_In\Мой контент\Книги"
        Set "Mask=File_2018-10-??_Original."

        Set "Dst=Z:\Книги.arc"

        Set Arc="C:\Program Files\WinRar\WinRar.exe" a -r -dh -m3 -s -rr5p -ts+ -y
        Set "Ext=rar"

        Set "LastDir="
        For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /A:D /B /O:N`) DO Set "LastDir=%%d"
        If "%LastDir%"=="" (Echo Folder not Found "%Src%\%Mask%\" &Pause &Exit /B 1)

        If Not Exist "%Dst%" Md "%Dst%"

        Pushd "%Src%" &&(
                If Not Exist "%Dst%\%LastDir%.*" (Echo "%Src%\%LastDir%\" &%Arc% "%Dst%\%LastDir%.%Ext%" "%LastDir%\")
                Popd
        )
pause
GoTo :Eof


UserX 05-11-2018 03:00 2839384

megaloman, да, с каталогами в папке Src это теперь прекрасно работает!

А можно ли сделать так, чтобы в каталоге Src могли быть не только вложенные папки, к которым будет применима такая маска, но и просто файлы, к которым будет применяться та же самая маска?
То есть, различия между папкой или файлом в каталоге Src для архивирования быть не должно, а маска должна одинаково относиться и к файлам, и к папкам.
Таким образом архивироваться в каталог Dst будут или файл, или папка из Src, в зависимости от того, чьё имя старше с точки зрения даты, являющейся частью имени.

Или такое возможно только либо-либо, то есть, либо в каталоге Src будут папки и тогда файлы будут игнорироваться, либо файлы, но тогда будут игнорироваться каталоги?

Я ещё раз извиняюсь за наглость. :unsure:

megaloman 05-11-2018 09:22 2839402

можно сделать так, чтобы в каталоге Src могли быть не только вложенные папки, к которым будет применима такая маска, но и просто файлы, к которым будет применяться та же самая маска
Код:

@Echo Off
cls
        Set "Src=Z:\Box_In\Мой контент\Книги"
        Set "Mask=File_2018-10-??_Original."

        Set "Dst=Z:\Книги.arc"

        Set Arc="C:\Program Files\WinRar\WinRar.exe" a -r -dh -m3 -s -rr5p -ts+ -y
        Set "Ext=rar"

        Pushd "%Src%" || (Echo Folder not Found "%Src%" &Pause &Exit /B 2)

        Set "Name="
        For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B /O:N`) DO Set "Name=%%d"
        If "%Name%"=="" (Echo File or Folder not Found "%Src%\%Mask%" &Pause &Exit /B 1)

        If Not Exist "%Dst%" Md "%Dst%"

        If Not Exist "%Dst%\%Name%.*" (Echo "%Src%\%Name%" &%Arc% "%Dst%\%Name%.%Ext%" "%Name%")
        Popd
pause
GoTo :Eof


UserX 05-11-2018 19:15 2839468

megaloman, Вы это сделали, и это работает!!
Огромное Вам спасибо! Вы - лучший.

Поделюсь с Вами мыслями.
Конечно, делать мешанину из файлов и папок в каталоге не совсем здОрово, но раз даже это проходит, значит, для Src, состоящего только из каталогов или только из файлов это будет работать точно, поскольку задача решена Вами в самом общем виде.
Потому просторы для этого решения открываются просто безграничные. Я пока не могу их даже полностью осмыслить до самого конца.
Практически, Вы сделали гипотезу батеньки Пуанкаре реальностью! :up:clapping:

PS
Вот осмыслю до конца и поглядим, какие новые проблемы создаст это решение. :)

UserX 05-11-2018 22:31 2839498

megaloman, произошло некоторое осмысление. :)

Проверил работу скрипта при очень разной маске и с весьма разнообразным содержимым каталога Src.
Даже при пустой маске, т.е.:
Set "Mask="

на мой взгляд работает правильно. Пустая маска полностью соответствсует маске *.*
Т.е.
Set "Mask=" полностью эквивалентна Set "Mask=*.*"
И это, на мой взгляд, вполне логично.

Однако, коль скоро эти два варианта работают идентично, можно ли попросить Вас о модификации Вашего последнего скрипта таким образом, чтобы при задании пустой маски, т.е. при указании:
Set "Mask=", как исключение, скрипт работал несколько иначе.
А именно, если маска пустая, чтобы архивировались из каталога Src в каталог Dst не самый последний, а ВСЕ папки и ВСЕ файлы, архивов которых ещё нет в Dst.

Тогда этот один скрипт станет универсальным и заменит собой (и даже расширит) скрипт из первой задачи.
Спасибо!

megaloman 06-11-2018 10:52 2839529

если маска пустая, чтобы архивировались из каталога Src в каталог Dst не самый последний, а ВСЕ папки и ВСЕ файлы, архивов которых ещё нет в Dst
Код:

@Echo Off
cls
        Set "Src=Z:\Box_In\Мой контент\Книги"
rem        Set "Mask=File_2018-10-??_Original."
        Set "Mask="

        Set "Dst=Z:\Книги.arc"

        Set Arc="C:\Program Files\WinRar\WinRar.exe" a -r -dh -m3 -s -rr5p -ts+ -y
        Set "Ext=rar"

        Pushd "%Src%" || (Echo Folder not Found "%Src%" &Pause &Exit /B 2)
        If Not Exist "%Dst%" Md "%Dst%" || (Echo Folder not Created "%Dst%" &Pause &Exit /B 3)

        If Not "%Mask%"=="" GoTo :OneFile
                Set /A Err=1
                For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B /O:N`) DO Set /A Err=0 &Call :OutArc "%%d"
                GoTo :End               
        :OneFile
                Set "Name="
                For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B /O:N`) DO Set "Name=%%d"
                If "%Name%"=="" (Echo File or Folder not Found "%Src%\%Mask%" &Pause &Exit /B 1)
       
                Call :OutArc "%Name%"
                Set /A Err=%ErrorLevel%
        :End
                Popd
pause
Exit /B %Err%

:OutArc
        If Not Exist "%Dst%\%~1.*" (Echo "%Src%\%~1" &%Arc% "%Dst%\%~1.%Ext%" "%~1")
Exit /B


UserX 06-11-2018 18:03 2839574

megaloman, Всё превосходно работает!

Но я, нагло используя плоды Вашего труда, немного переформулировал свою же задачу, дабы уже не было никаких ограничений по маске, и маска оставалась только маской без всяких посторонних смыслов.

Для того, чтобы не грузить маску иным, нехарактерным для неё смыслом, я решил ввести в скрипт дополнительный параметр "Mode".
Если установить Set "Mode=1", то получим однофайловый режим, а при любых других значениях Mode, например, если установить Set "Mode=0", получим режим архивации всех файлов из Src, архивов которых ещё нет в Dst.
Ну, и ещё добавил режим сортировки, дабы в однофайловом режиме архивировался либо первый, либо последний файл или каталог в зависимости от заданного режима сортировки.
Set "Ascending=" прямая сортировка - архивируется последний каталог или файл по маске.
Set "Ascending=-" обратная сортировка - архивируется первый каталог или файл по маске.

Естественно, ничего моего в полученном скрипте нет, всё полностью сделано из Вашего последнего скрипта. Просто он теперь полностью решает вместе и первую и вторую задачи по маске.

Прошу Вас, как настоящего профессионала, на всякий случай, посмотреть и проверить - не напорол ли я каких-либо косяков при "модернизации" Вашего превосходного исходника.
Ну, или, может можно сделать как-то изящнее, поскольку изначально задача мною озвучивалась совсем иначе.

Модернизированный батник

@Echo Off
cls
;Rem Mode must be set to 1 for OneFileMode or any value (0) for AllFilesMode
Set "Mode=1"
;Rem Set "Mode=0"

Set "Src=C:\111\Src"
Set "Dst=C:\111\Dst"
Set "Mask=??10??"
;Rem Маска всех октябрьских файлов и каталогов.
;Rem Mask - Mask for catalogs or files in Src.

;Rem Set "Ascending="
;Rem "Ascending=" прямая сортировка - архивируется последний каталог или файл по маске
Set "Ascending=-"
;Rem Set "Ascending=-" обратная сортировка - архивируется первый каталог или файл по маске

Set Arc="C:\Program Files\WinRar\WinRar.exe" a -r -ma4 -m5 -rr5p -ts+ -y
Set "Ext=rar"

Pushd "%Src%" || (Echo Folder not Found "%Src%" &Pause &Exit /B 2)
If Not Exist "%Dst%" Md "%Dst%" || (Echo Folder not Created "%Dst%" &Pause &Exit /B 3)

If "%Mode%"=="1" GoTo :OneFile
Set /A Err=1
For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B /O:%Ascending%N`) DO Set /A Err=0 &Call :OutArc "%%d"
GoTo :End
:OneFile
Set "Name="
For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B /O:%Ascending%N`) DO Set "Name=%%d"
If "%Name%"=="" (Echo File or Folder not Found "%Src%\%Mask%" &Pause &Exit /B 1)

Call :OutArc "%Name%"
Set /A Err=%ErrorLevel%
:End
Popd

pause
Exit /B %Err%

:OutArc
If Not Exist "%Dst%\%~1.*" (Echo "%Src%\%~1" &%Arc% "%Dst%\%~1.%Ext%" "%~1")
Exit /B


И ещё пара вопросов:
1) Команда "pause" в скрипте несёт какую-то иную цель, кроме сообщения о том, что батник выполнился и для продолжения нужно нажать любую клавишу? Имеется ввиду, удаление этой команды из скрипта не отразится на чём-либо ещё в его работе?
Просто мой опыт говорит, что порой что-то, на первый взгляд, очевидное таковым не всегда является в реалии. Поэтому, лучше лишний раз уточнить.
2) Как правильнее подавить вывод сообщений о результатах работы этого батника, если использовать его в заданиях Шедулера Виндовс? Ставить после каждой команды "> Nul" ? Или это делается как-то однократно в самом начале батника?
Вообще, что, на Ваш взгляд, имело бы смысл подправить в синтаксисе батника при его использовании в задании Шедулера?

megaloman 06-11-2018 21:44 2839599

Вот оптимизированный вариант ориентированный на планировщик
Код:

@Echo Off
cls
        Set "Src=Z:\Box_In\Мой контент\Книги"
        Set "Mask=File_2018-10-??_Original."
rem        Set "Mask="

rem        Set "DirKey=/O:-N /A:D"
        Set "DirKey=/O:-N"

        Set "Dst=Z:\Книги.arc"
        Set "Log=%Dst%\%~nx0.log"

        Set Arc="C:\Program Files\WinRar\WinRar.exe" a -r -dh -m3 -s -rr5p -ts+ -y
        Set "Ext=rar"

        Pushd "%Src%" || (Set MSG=Folder not Found "%Src%" &Set /A Err=2 &GoTo :End)
        If Not Exist "%Dst%" Md "%Dst%" || (Set MSG=Folder not Created "%Dst%" &Set /A Err=3 &GoTo :End)

        Set /A Err=1

        If    "%Mask%"=="" For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B %DirKey%`) DO (Set /A Err=0 &Call :OutArc "%%d")
        If Not "%Mask%"=="" For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B %DirKey%`) DO (Set /A Err=0 &Call :OutArc "%%d" &GoTo :End)

        :End
        Popd

        If "%Err%"=="1" (Set MSG=File or Folder not Found "%Src%\%Mask%" %DirKey%)
        If Not "%Err%"=="0" >>"%Log%" Echo %Date% %Time% %Msg%
pause
Exit /B %Err%

:OutArc
        If Not Exist "%Dst%\%~1.*" (
                >>"%Log%" Echo %Date% %Time% "%Src%\%~1"
                %Arc% "%Dst%\%~1.%Ext%" "%~1"
        )
Exit /B

1. Pause можно/нужно закомментировать или убить
2. Если использовать батник в заданиях планировщика, то, наверное, надо иметь лог-файл. Если не надо, закомментируйте выделенные строки.
3. Для настройки работы команды Dir лучше использовать явным образом ключи. Делаем команду Dir /? и изучаем ключи и присваиваем нужный список переменной DirKey.
В частности, Set "DirKey=/O:-N /A:D" даст алфавитную сортировку в обратном порядке и включит в рассмотрение только папки.
4. Маску оставил как есть. В принципе можно легко ввести специальную переменную. Но не увидел большого смысла.
5. Я использую Winrar.exe, подозреваю, он работает быстрее.
Можно, конечно, использовать rar.exe, например:
Set Arc="C:\Program Files\WinRar\Rar.exe" a -r -dh -m3 -s -rr5p -ts+ -y
и подавить его вывод
%Arc% "%Dst%\%~1.%Ext%" "%~1" >nul
6.
Цитата:

Цитата UserX
Set "Mask=??10??" »

Я не очень вчитывался в код, но эту маску я не понимаю. Кстати, для читабельности кода используйте тег Code

UserX 06-11-2018 23:24 2839613

Цитата:

Цитата megaloman
Я использую Winrar.exe, подозреваю, он работает быстрее. »

Попытка использовать в Windows 2008 R2 (x64) rar.exe вообще не прошла. Поэтому, только WinRar.exe.

Цитата:

Цитата megaloman
Я не очень вчитывался в код, но эту маску (??10??) я не понимаю »

Да это частный случай маски для файлов с именем YYMMDD, где в данном случае месяц указан конкретно ММ==10, т.е. октябрь.

Решил-таки оставить свою переменную Mode, поскольку без неё не будет работать произвольная маска выбора ВСЕХ файлов по заданной маске при их архивации, а будет иметься ввиду только маска *.* (сам ведь такую заказывал :) )
Собственно, только ради этого смысла и была введена переменная Mode

Огромное Вам спасибо за проделанную работу, представленный мастер-класс, в результате которого мною была получена бесценная информация. Спасибо Вам ещё раз.

UserX 07-11-2018 03:46 2839622

megaloman, Предложенный Вами последний оптимизированный батник перестал работать так, как он работал ранее и так, как мне было нужно. Изменить его так, чтобы он остался оптимизмрованным и при этом работал так, как он работал до последней оптимизации мне не удалось.

Всё-таки, мне очень нужно ввести переменную Mode, поскольку она позволяет работать с заданной маской в любом из двух режимов:
в режиме AllFilesMode (с заданной маской) и в режиме OneFileMode (тоже с заданной маской).
То, что приведено ниже, сейчас работает так, как нужно, но оно не оптимизировано и нет вывода логов.
Пожалуйста, помогите оптимизировать для планировщика приведённый батник, в котором указываются режимы Mode 0 и Mode 1.
Заранее большое спасибо.

Рабочий, но неоптимизированный батник

Код:

@Echo Off
;Rem Mode must be set to 1 for OneFileMode or any value (0) for AllFilesMode
Set "Mode=0"
;Rem Set "Mode=1"

Set "Src=C:\111\Src"
Set "Dst=C:\111\Dst"
Set "Mask=File_2018-10-??_Original."
;Rem  Mask - Mask for catalogs or files in Src.

Set "DirKey=/O:N"
Rem Set "DirKey=/O:-N"


Set Arc="C:\Program Files\WinRar\WinRar.exe" a -r -ma4 -m5 -rr5p -ts+ -y
Set "Ext=rar"

Pushd "%Src%" || (Echo Folder not Found "%Src%" &Exit /B 2)

If Not Exist "%Dst%" Md "%Dst%" || (Echo Folder not Created "%Dst%" &Exit /B 3)

If "%Mode%"=="1" GoTo :OneFileMode
:AllFilesMode
  Set /A Err=1
  For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B %DirKey%`) DO Set /A Err=0 &Call :OutArc "%%d"
  GoTo :End

:OneFileMode
  Set "Name="
  For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B %DirKey%`) DO Set "Name=%%d"
  If "%Name%"=="" (Echo File or Folder not Found "%Src%\%Mask%" &Exit /B 1)

  Call :OutArc "%Name%"
  Set /A Err=%ErrorLevel%
:End
  Popd

Exit /B %Err%

:OutArc
  If Not Exist "%Dst%\%~1.*" (Echo "%Src%\%~1" &%Arc% "%Dst%\%~1.%Ext%" "%~1")
Exit /B


megaloman 07-11-2018 10:01 2839641

Цитата:

Цитата UserX
последний оптимизированный батник перестал работать так, как он работал ранее и так, как мне было нужно. »

здесь нет конкретики, что конкретно не так?
Здесь вариант с так любимой Вами переменной Mode
Код:

@Echo Off
cls
        Set "Src=Z:\Box_In\Мой контент\Книги"
        Set "Mask=File_2018-10-??_Original."

        Set /A Mode=1                &Rem 1= 1 файл/папка, 0=все файлы/папки по маске

        Set "DirKey=/O:-N"        &Rem если выбирается один файл/папка, то выберется самый последний по алфавиту

        Set "Dst=Z:\Книги.arc"
        Set "Log=%Dst%\%~nx0.log"  &Rem Путь к лог-файлу. Можно указать в любом доступном месте с любым именем.

        Set Arc="C:\Program Files\WinRar\WinRar.exe" a -r -dh -m3 -s -rr5p -ts+ -y
        Set "Ext=rar"

        Pushd "%Src%" || (Set MSG=Folder not Found "%Src%" &Set /A Err=2 &GoTo :End)
        If Not Exist "%Dst%" Md "%Dst%" || (Set MSG=Folder not Created "%Dst%" &Set /A Err=3 &GoTo :End)

        Set /A Err=1

        If %Mode%==0 For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B %DirKey%`) DO (Set /A Err=0 &Call :OutArc "%%d")
        If %Mode%==1 For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B %DirKey%`) DO (Set /A Err=0 &Call :OutArc "%%d" &GoTo :End)

        :End
        Popd
        If "%Err%"=="1" (Set MSG=File or Folder not Found "%Src%\%Mask%" %DirKey%)
        If Not "%Err%"=="0" >>"%Log%" Echo %Date% %Time% %Msg%

pause
Exit /B %Err%

:OutArc
        If Not Exist "%Dst%\%~1.*" (
                >>"%Log%" Echo %Date% %Time% "%Src%\%~1"
                %Arc% "%Dst%\%~1.%Ext%" "%~1"
        )
Exit /B


UserX 07-11-2018 18:23 2839727

megaloman, опробовал Ваш последний батник.
Что интересно - результат его работы в режиме Mode=0 (AllFilesMode) зависит от значения DirKey
То есть, в указанном режиме Mode=0 (AllFilesMode) при DirKey=/O:-N и DirKey=/O:N результаты работы в каталоге Dst существенно между собой различаются, хотя, по логике дел, они должны бы быть одинаковы. Если, конечно, я ничего не упускаю из вида.
Правильная, на мой взгляд, работа в режиме Mode=0 (AllFilesMode) достигается только в случае установки в команде Dir ключа прямой сортировки, т.е. при DirKey=/O:N.
Это, видимо, значит, что в режиме Mode=0 (AllFilesMode) от DirKey нужно вообще оказаться и явно устанавливать ключ прямой сортировки для Dir, т.е. /O:N.
С учётом изложенного, модифицированная версия полностью работающего батника, кажется наконец-то, обретает завершённый вид:
Незначительная модификация

Код:

@Echo Off
cls
    Set "Mask=File_2018-10-??_Original."

    Set "Src=Z:\Box_In\Мой контент\Книги"
    Set "Dst=Z:\Книги.arc"

    Set "Log=%Dst%\%~nx0.log"  &Rem Путь к лог-файлу. Можно указать в любом доступном месте с любым именем.

    Set /A Mode=1        &Rem Mode=1 - один файл/папка по маске; Mode=0 - все файлы/папки по маске
    Set "DirKey=/O:-N"    &Rem если выбран режим один файл/папка (Mode=1), то выберется самый последний по алфавиту
    Rem Set "DirKey=/O:N"    &Rem если выбран режим один файл/папка (Mode=1), то выберется самый первый по алфавиту

    Set Arc="C:\Program Files\WinRar\WinRar.exe" a -r -dh -m3 -s -rr5p -ts+ -y
    Set "Ext=rar"

    Pushd "%Src%" || (Set MSG=Folder not Found "%Src%" &Set /A Err=2 &GoTo :End)
    If Not Exist "%Dst%" Md "%Dst%" || (Set MSG=Folder not Created "%Dst%" &Set /A Err=3 &GoTo :End)

    Set /A Err=1

    If %Mode%==0 For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B /O:N`) DO (Set /A Err=0 &Call :OutArc "%%d")
    If %Mode%==1 For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B %DirKey%`) DO (Set /A Err=0 &Call :OutArc "%%d" &GoTo :End)

    :End
    Popd
    If "%Err%"=="1" (Set MSG=File or Folder not Found "%Src%\%Mask%" %DirKey%)
    If Not "%Err%"=="0" >>"%Log%" Echo %Date% %Time% %Msg%

rem pause
Exit /B %Err%

:OutArc
    If Not Exist "%Dst%\%~1.*" (
        >>"%Log%" Echo %Date% %Time% "%Src%\%~1"
        %Arc% "%Dst%\%~1.%Ext%" "%~1"
    )
Exit /B


Посмотрите, пожалуйста.

megaloman 07-11-2018 18:58 2839729

Цитата:

Цитата UserX
Что интересно - результат его работы в режиме Mode=0 (AllFilesMode) зависит от значения DirKey
То есть, при DirKey=/O:-N и DirKey=/O:N результаты работы в каталоге Dst существенно между собой отличаются, хотя, по логике дел, они должны бы быть одинаковы. Если, конечно, я ничего не упускаю.
Правильная, на мой взгляд, работа в режиме Mode=0 (AllFilesMode) достигается только в случае установки в команде Dir ключа прямой сортировки, т.е. при DirKey=/O:N. »

- категорически с Вами не согласен.Cущественно между собой отличаются - это как? Только по времени (порядку) создания архивов. В этом режиме ключ сортировки вообще не имеет значения на количество и номенклатуру созданных архивов. Можете его вообще сделать пустым или убить - по умолчанию Dir выдаёт прямую алфавитную сортировку (если иное не прописано в системе). Он был оставлен только для единообразия цикла. Я протестировал. Убедился. Что-то Вы при тестировании делаете некорректно. Например, не удаляете упакованные после предыдущего тестирования файлы. Пересчитайте кол-во архивов (можете в лог-файле) и убедитесь в совпадении. Посмотрите в лог-файле список упакованных файлов при прямой сортировке и обратной. Они отличаются только обратным порядком.
Дело Ваше. (1.)Клиент всегда прав. (2.)Если клиент не прав, смотри (1.) Успехов!

PS. Обратите внимание, что в посте #18 для одного файла выбирается последний в списке Dir файл, а в постах #23, #26 выбирается первый. Вот тут и имеет значение /O:N в старых вариантах и /O:-N в последних вариантах.

UserX 07-11-2018 20:13 2839743

Цитата:

Цитата megaloman
- категорически с Вами не согласен.»

Я веду речь только об одном конкретном режиме, а именно о режиме с установленным Set /A Mode=0 (то есть, если установлен режим всех файлов по заданной маске).
В этом одном режиме результаты работы батника в папке Dst при "SetKey=/O:N" и "SetKey=/O:-N" могут получиться совершенно разные. Но я вполне допускаю, что при некоторых вариантах маски эти результаты могут быть и совершенно идентичными.
Но разве результаты работы сами по себе не является реальностью? Я ведь эти резульаты работы никак не подтасовывал и не пытался ввести Вас в заблуждение. С чем тут можно соглашаться или не соглашаться?
Меня и самого это удивило. Но факт есть факт, вне зависимости от того, согласен ли кто угодно с ним или нет.

Цитата:

Цитата megaloman
Cущественно между собой отличаются - это как»

Отличаются самими архивами (что из файлов/папок из Src запаковывается в Dst) и их количеством (сколько файлов/папок из Src запаковывается в Dst).

Цитата:

Цитата megaloman
Что-то Вы при тестировании делаете некорректно. Например, не удаляете упакованные после предыдущего тестирования файлы.»

Нет, перед каждым тестом я каждый раз полностью очищал содержимое папки Dst.
Да и как такое возможно - "сделать некорректное тестирование"? По-моему, тестирование не может быть корректным или некорректным. Оно может быть просто тестированием.

Готов выложить Вам примерное содержимое папки Src, которое в режиме с установленным режимом Set /A Mode=0 (то есть, если установлен режим всех файлов по заданной маске), даёт разные результаты в папке Dst по количеству и видам созданных архивов при изменении ключа сортировки в Dir c прямого на обратный, чтобы вы смогли лично в этом убедиться.
Выложить свой тест?

UserX 07-11-2018 20:47 2839751

Ключи:
Set /A Mode=0
Set "Mask=??10??.*"
Dir исходной папки Src

Код:

Содержимое папки C:\111\Src

07.11.2018  20:41    <DIR>          .
07.11.2018  20:41    <DIR>          ..
05.11.2018  19:03    <DIR>          181027
05.11.2018  02:39    <DIR>          181028
01.10.2018  10:07          474 940 181028.jpg
05.11.2018  18:52    <DIR>          181029
01.10.2018  10:07          474 940 181029.jpg
05.11.2018  19:21    <DIR>          181030
01.10.2018  10:07          474 940 181030.jpg
05.11.2018  19:04    <DIR>          181103
01.10.2018  10:07          474 940 181103.jpg
              4 файлов      1 899 760 байт
              7 папок  4 155 273 216 байт свободно


Dir результата в Dst при /N:O

Код:

Содержимое папки C:\111\Dst

07.11.2018  20:54    <DIR>          .
07.11.2018  20:54    <DIR>          ..
07.11.2018  20:53        11 316 072 181027.rar
07.11.2018  20:53          486 766 181028.jpg.rar
07.11.2018  20:53        1 270 083 181028.rar
07.11.2018  20:53          486 766 181029.jpg.rar
07.11.2018  20:53        11 316 072 181029.rar
07.11.2018  20:53          486 766 181030.jpg.rar
07.11.2018  20:53        11 316 072 181030.rar
              7 файлов    36 678 597 байт
              2 папок  4 165 160 960 байт свободно


Dir результата в Dst при /N:-O

Код:

Содержимое папки C:\111\Dst

07.11.2018  20:49    <DIR>          .
07.11.2018  20:49    <DIR>          ..
07.11.2018  20:46        11 316 072 181027.rar
07.11.2018  20:46          486 766 181028.jpg.rar
07.11.2018  20:46          486 766 181029.jpg.rar
07.11.2018  20:46          486 766 181030.jpg.rar
              4 файлов    12 776 370 байт
              2 папок  4 189 036 544 байт свободно


UserX 07-11-2018 21:14 2839756

Цитата:

Это сообщение посчитали полезным следующие участники:
megaloman
Ну, слава Богу! Мне удалось не обмануть Ваших ожиданий. :)

Спасибо Вам за всю проделанную Вами работу и за Ваше долготерпение, которое Вы проявили к оппоненту, несмотря ни на что.
Удачи Вам!

megaloman 07-11-2018 22:35 2839770

UserX,
Цитата:

Цитата UserX
чтобы при наличии в каталоге Dst архивов (*.rar, *.zip, *.7z и пр.) »

Хаос в данных == непредсказуемому результату.
При анализе наличия архива по маске Файл.* получим соответствие с Файл.jpg.*=Файл.* с ключом /O:-N
Гарантировать, что при ключе /O:N не получится еще какой-нибудь непредсказуемый пропуск, не берусь.
Чтобы результат был предсказуем (работа батника надежнее),то:

Либо считаем, что все архивы имеют расширение %Ext% (в нашем случае Rar), тогда исправление:
Код:

:OutArc
        If Not Exist "%Dst%\%~1.%Ext%" (

Либо надо перечислить все возможные расширения архивов
Код:

@Echo Off
cls
        Set "Src=Z:\Box_In"
        Set "Mask=??10??.*"

        Set /A Mode=0                &Rem 1= 1 файл/папка, 0=все файлы/папки по маске

        Set "DirKey=/O:-N"        &Rem /O:-N если выбирается один файл/папка, то выберется самый последний по алфавиту

        Set "Dst=Z:\Книги.arc"
        Set "Log=%Dst%\%~nx0.log"  &Rem Путь к лог-файлу. Можно указать в любом доступном месте с любым именем.

        Set Arc="C:\Program Files\WinRar\WinRar.exe" a -r -dh -m3 -s -rr5p -ts+ -y
        Set "Ext=rar"

        Set "AllExt=rar zip 7z arc"

        Pushd "%Src%" || (Set MSG=Folder not Found "%Src%" &Set /A Err=2 &GoTo :End)
        If Not Exist "%Dst%" Md "%Dst%" || (Set MSG=Folder not Created "%Dst%" &Set /A Err=3 &GoTo :End)

        Set /A Err=1

        If %Mode%==0 For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B %DirKey%`) DO (Set /A Err=0 &Call :OutArc "%%d")
        If %Mode%==1 For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B %DirKey%`) DO (Set /A Err=0 &Call :OutArc "%%d" &GoTo :End)

        :End
        Popd
        If "%Err%"=="1" (Set MSG=File or Folder not Found "%Src%\%Mask%" %DirKey%)
        If Not "%Err%"=="0" >>"%Log%" Echo %Date% %Time% %Msg%

pause
Exit /B %Err%

:OutArc
        FOR %%e IN (%AllExt%) DO If Exist "%Dst%\%~1.%%~e" Exit /B 0

        >>"%Log%" Echo %Date% %Time% "%Src%\%~1"
        %Arc% "%Dst%\%~1.%Ext%" "%~1"
Exit /B 0


И вааще, смесь файлов/папок с одинаковыми именами и разными расширениями может дать неожиданный результат при любых алфавитных сортировках даже при отборе 1 файла с маской с расширением .*
Удалите в Вашем наборе папку 181027 и, в зависимости от ключа сортировки, будете иметь
или 181028.rar или 181030.jpg.rar
Так что при смеси кони/люди (файлы/папки c одинаковыми именами, но разными расширениями) откажитесь от маски с расширением .* и используйте только жестко определённое расширение.

UserX 07-11-2018 23:59 2839778

Цитата:

Цитата megaloman
И вааще, смесь файлов/папок с одинаковыми именами и разными расширениями может дать неожиданный результат »

Я попробовал давать Вашему батничку на съедение весьма изощрённый наборчик ядрёной смеси. И он на ура справился со всем разнообразием, которое я ему подсовывал. При этом я всегда получал от него те результаты работы, которые и надеялся получить.
То есть, Ваш батник с честью выдержал все мои корявые тесты и ни разу не подвёл и не обманул моих ожиданий.
Единственное, я ещё раз хочу настоятельно уточнить, что в строке, касающейся прохождения проверки, что установлен режим Mode==0, я явно задаю прямое направление сортировки команды Dir ключом /O:N, т.е. я изменил одну Вашу строку в исходнике так (выделено жирным):
If %Mode%==0 For /F "usebackq delims=" %%d IN (`2^>nul Dir "%Src%\%Mask%" /B /O:N`) DO (Set /A Err=0 &Call :OutArc

И это принципиально для получения правильного результата работы батника при хаосе в каталоге Src.

Что же касается мешанины в каталоге Src, так она специально и создавалась таковой для тестирования. В реалии у меня такого бардака в Src, конечно же, нет. Но ведь проверить-то было нужно! :)
Считаю, что правильно написанная програма справляется со всеми вариантами, что, собственно, и продемонстрировал написанный Вами батник.

megaloman 08-11-2018 00:10 2839779

UserX, Лог-файл создаётся? Путь к нему указан правильно? Я получил аналогичный результат, когда указал кривой путь к лог-файлу

Цитата:

Цитата UserX
правильно написааня программка справляется со всеми вариантами »

Один из столпов программирования утверждал: всегда можно подобрать данные, способные одурачить программу

UserX 08-11-2018 01:00 2839780

Цитата:

Цитата megaloman
Лог-файл создаётся? »

Чёрт подери, я же у себя поменял Ваш параметр Log на LogFile, да во втором варианте позабыл его везде поправить.
Сейчас поправил, и всё прекрасно заработало.
Извините меня, пожалуйста, за невнимательность и ложную тревогу. :(

Собственно, почему я переименовал Log в LogFile. Хотел ещё ввести у себя параметр Log, типа:
Set "Log=Yes"
для того, чтобы вставить проверку - создавать или нет log-файл. Да что-то в моих неумелых руках не задалось... :)

Iska 08-11-2018 02:32 2839784

Цитата:

Цитата megaloman
по умолчанию Dir выдаёт прямую алфавитную сортировку »

Неа. Что возвращает функция WinAPI FindFirstFile/FindNextFile, то и выдаёт. Просто на NTFS записи каталога уже упорядочены по именам-расширениям. А для FATx это не так:
Скрытый текст

— там имена возвращаются в порядке создания записей каталога.

UserX 08-11-2018 02:59 2839786

Цитата:

Цитата Iska
— там имена возвращаются в порядке создания записей каталога. »

Ёпрст! Получается, что ключ сортировки по имени (/o:n) у команды Dir просто не работает?
Как же так? Ведь это же хаос какой-то! Ну, по умолчанию - ладно. Что там Dir выдаёт по умолчанию известно только ей, хотя, да, я ещё помню, что в fat32 командой Dir по умолчанию выдаются имена в порядке их создания.
Но ведь если явно указан ключ сортировки, то почему он не работает??
Я не понимаю...

Iska 08-11-2018 03:06 2839787

Цитата:

Цитата UserX
Ёпрст! Получается, что ключ сортировки по имени (/o:n) у команды Dir просто не работает? »

Работает.

Цитата:

Цитата UserX
хотя, да, я помню,ещё что в fat32 командой Dir по умолчанию выдаются имена в порядке их создания. »

Именно так. Об этом я и написал.

Цитата:

Цитата UserX
Но ведь если явно указан ключ сортировки, то почему он не работает?? »

Работает.

Неверным является только одно предположение — что по умолчанию (в случае отсутствия параметра /o, отсутствия переменной окружения DIRCMD, отсутствия в содержимом переменной окружения DIRCMD параметра /o) команда dir возвращает имена-расширения файлов и каталогов из оглавления каталога в лексикографическом порядке. Это не так.

UserX 08-11-2018 17:38 2839903

Цитата:

Цитата Iska
Работает. »

Действительно работает. Я просто был невнимателен. Извините, пожалуйста.


Время: 08:38.

Время: 08:38.
© OSzone.net 2001-