Пакетный сценарий перебирает папки, архивирует каждый файл в папке и перемещает его в соответствующую папку в другом месте. - PullRequest
0 голосов
/ 19 октября 2018

У меня есть два набора папок:

«C: \ temp \ eFS_manual_temp» содержит набор подпапок.Другой каталог, C: \ temp \ eFS_manual \ eFS, содержит тот же набор подпапок.

Я хочу использовать приведенный ниже пакетный скрипт, чтобы сжать все файлы в подпапках, по одной папке за раз, и переместить файлы ZIP во вторичное расположение с той же структурой папок:

SET SourceDir=C:\temp\eFS_manual\_temp
SET DestDir=C:\temp\eFS_manual\eFS

for /D %%a in ("%SourceDir%") do (

    CD /D "C:\Program Files\WinRAR"
    FOR /F "TOKENS=*" %%F IN ('DIR /B /A-D "%SourceDir%\%%a"') DO (
        RAR.exe a -ep "%DestDir%\%%a\%%~NF.zip" "%SourceDir%\%%a\%%~NXF"
    )

)

Я получаю следующую ошибку: неверный синтаксис имени файла, имени каталога или метки тома.

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

Несколько строк кода пакетного файла содержат несколько ошибок.

Первая строка находится в строке for /D %%a in ("%SourceDir%") do.Параметр /D игнорируется FOR для набора в круглых скобках, не содержащего подстановочных знаков.Это легко увидеть, открыв окно командной строки и запустив:

for /D %I in ("%SystemRoot%") do @echo %I

Эта командная строка просто печатает "C:\Windows", что в точности соответствует строке в скобках.

Так что давайте запустим этокомандная строка с добавленным подстановочным знаком:

for /D %I in ("%SystemRoot%\*") do @echo %I

Вывод намного лучше, поскольку в списке перечислены все не скрытые подкаталоги в системном каталоге Windows.

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

В командной строке имеется несколько ошибок

FOR /F "TOKENS=*" %%F IN ('DIR /B /A-D "%SourceDir%\%%a"') DO

%%a расширится до полного квалифицированного имениПодкаталог в %SourceDir% во внешней FOR командной строке будет правильным. FOR присваивает указанной переменной цикла только имя не скрытого каталога на множестве в круглых скобках, не содержит пути, т. Е. Просто for /D %I in (*) do @echo %I будет использоваться для обработки не скрытых подкаталогов в текущем каталоге.Но если в скобках указан абсолютный или относительный путь, FOR назначает указанной переменной цикла имя каталога с указанным абсолютным или относительным путем.Такое поведение наблюдается при запуске в окне командной строки следующих команд:

cd /D %SystemDrive%\
for /D %I in (.\*) do @echo %I
for /D %I in (%SystemDrive%\*) do @echo %I

RAR.exe создает целое дерево каталогов для указанного каталога назначения автоматически при извлечении архива.Но каталог назначения должен уже существовать при создании архива.Поэтому рекомендуется убедиться в целевом каталоге, что текущий подкаталог из исходного каталога также существует в целевом каталоге.

FOR выполняет встроенную командную строку DIR вотдельный командный процесс запущен с cmd.exe /C в фоновом режиме и захватывает все выходные строки для обработки STDOUT этого отдельного командного процесса с помощью DIR . DIR в этом случае выводит только имена файлов с расширением для всех файлов, включая файлы со скрытым набором атрибутов, найденных в указанном каталоге.

Захваченные пустые строки пропускаются FOR , а также строки, начинающиеся с ;, поскольку eol=; является значением по умолчанию.tokens=* приводит к удалению ведущих пробелов / табуляций из захваченной строки, и если что-то осталось, оставшаяся строка присваивается указанной переменной цикла для обработки командами в теле FOR петля.Такое поведение не хорошо в случае, если имя файла начинается с пробела или точки с запятой.Лучше было бы использовать delims= для полного отключения режима разбиения строк и присвоения полного имени файла указанной переменной цикла.

Но даже после исправления всех этих ошибок все равно будет проблема.Инструкция для консольного приложения Rar.exe представляет собой текстовый файл Rar.txt в папке WinRAR программных файлов.Сверху ясно объясняется, что Rar.exe поддерживает только RAR архивов.Он не поддерживает другие типы архивов, такие как ZIP , поскольку WinRAR.exe поддерживает.Поэтому Rar.exe нельзя использовать для создания файлов архива ZIP.

Примеры упрощают жизнь разработчиков, поэтому давайте начнем с примера:

Исходный каталог C:\temp\eFS_manual\_temp содержит следующие каталоги ифайлы:

  • Подпапка 1
    • Файл 1.txt
    • ; Комментарий и отчет!it.readme
    • Файл 2.csv
  • Подпапка 2
    • .htaccess
    • Еще один%file.txt

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

  • имени файла, начинающегося с пробела;
  • имя файла, начинающееся с точки с запятой;
  • имя файла, содержащее восклицательный знак;
  • имя файла, содержащее знак процента;
  • имя файла, начинающееся с точки и не имеющее больше точки.

Ни один из файлов и каталогов не имеет установленного скрытого атрибута.

Целевой каталог C:\temp\eFS_manual\eFS должен содержать послеТем не менее, пакетное выполнение файла:

  • Подпапка 1
    • Файл 1.zip
    • ; Комментарий и отчет!it.zip
    • Файл 2.zip
  • Подпапка 2
    • .htaccess.zip
    • Oneбольше% file.zip

И, конечно, ZIP-файлы - это действительно ZIP-сжатые архивные файлы, содержащие только один сжатый файл без пути.

Эта цель можетможно достичь с помощью:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceDir=C:\temp\eFS_manual\_temp"
set "DestDir=C:\temp\eFS_manual\eFS"

for /D %%I in ("%SourceDir%\*") do (
    md "%DestDir%\%%~nxI" 2>nul
    for %%J in ("%%I\*") do (
        if not "%%~nJ" == "" (
            "%ProgramFiles%\WinRAR\WinRAR.exe" a -afzip -cfg- -ep -ibck -inul -m5 -y -- "%DestDir%\%%~nxI\%%~nJ.zip" "%%J"
        ) else (
            "%ProgramFiles%\WinRAR\WinRAR.exe" a -afzip -cfg- -ep -ibck -inul -m5 -y -- "%DestDir%\%%~nxI\%%~xJ.zip" "%%J"
        )
    )
)

endlocal

Чтобы увидеть, как работает этот пакетный файл, измените первую строку на @echo on и запустите пакетный файл из окна командной строки, как в этом случае вывод командного процессора Windowsкаждая строка после предварительной обработки / синтаксического анализа, как описано в Как интерпретатор сценариев команд Windows (CMD.EXE) анализирует сценарии? перед выполнением командной строки.

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

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceDir=C:\temp\eFS_manual\_temp"
set "DestDir=C:\temp\eFS_manual\eFS"

for /F "eol=| delims=" %%I in ('dir "%SourceDir%\*" /AD /B 2^>nul') do (
    md "%DestDir%\%%I" 2>nul
    for /F "eol=| delims=" %%J in ('dir "%SourceDir%\%%I\*" /A-D /B 2^>nul') do (
        if not "%%~nJ" == "" (
            "%ProgramFiles%\WinRAR\WinRAR.exe" a -afzip -cfg- -ep -ibck -inul -m5 -y -- "%DestDir%\%%I\%%~nJ.zip" "%SourceDir%\%%I\%%J"
        ) else (
            "%ProgramFiles%\WinRAR\WinRAR.exe" a -afzip -cfg- -ep -ibck -inul -m5 -y -- "%DestDir%\%%I\%%~xJ.zip" "%SourceDir%\%%I\%%J"
        )
    )
)

endlocal

Этот пакетный файл учитывает, что DIR с опциейion /B и без опции /S выводит имена каталогов и файлов всегда без пути.

Пожалуйста, прочитайте статью Microsoft о Использование операторов перенаправления команд для объяснения 2>nul.Оператор перенаправления > должен быть экранирован с помощью символа вставки ^ в командной строке FOR , чтобы интерпретироваться как литеральный символ, когда интерпретатор команд Windows обрабатывает эту командную строку перед выполнением команды FOR , котораявыполняет встроенную командную строку dir в отдельном командном процессе, запущенном в фоновом режиме.

Командная строка WinRAR создается

  • при запуске WinRAR,
  • открытие из последнего меню Справка справка, нажав на первый пункт меню Разделы справки ,
  • навигация по вкладке Содержимое для элемента списка Режим командной строки ,
  • , расширяющий этот элемент списка нажатием [+],
  • нажатие на элемент списка Командная строкасинтаксис и копирование жирной строки вверху в качестве шаблона для командной строки,
  • с расширением влево в списке, нажав [+] элемент списка Commands и нажав Буквенные команды list и выберите a в качестве команды, используемой для этой задачи,
  • , развернув влево в списке, щелкнув по [+] элементу подсписка Переключения и нажав Список буквенных переключателей и выберите переключатели, подходящие для этой задачи,
  • и, наконец, используйте правильные строки для имени файла архива и имени файла для архива.

Для пониманияиспользуемые команды и как они работают, откройте окно командной строки, выполните там следующие команды и полностью прочитайте все страницы справки, отображаемые для каждой команды.

  • dir /?
  • echo /?
  • endlocal /?
  • for /?
  • if /?
  • md /?
  • set /?
  • setlocal /?
0 голосов
/ 20 октября 2018

Самой сложной частью этого для меня было получение нового пути к каталогу, встроенного в $NewDir.Как только это было сделано, использовать Compress-Archive для создания архива в формате .zip стало легко.Предполагается, что вы хотите создать пустые каталоги, если исходный каталог не содержит файлов.

Так как вы хотели архивный файл .zip, я использовал Compress-Archive.Если вы хотите использовать другой инструмент (rar.exe или 7z.exe), который можно использовать вместо этого с некоторыми изменениями.

$SourceDir = 'C:\src\t'
$DestDir = 'C:\src\tarch'

Get-ChildItem -Recurse -Directory -Path $SourceDir |
    ForEach-Object {
        $SubName = $_.FullName.Replace($SourceDir, '')
        $NewDir = $DestDir + $SubName
        if (-not (Test-Path -Path $NewDir)) { New-Item -ItemType Directory -Path $NewDir }

        $files = Get-ChildItem -File -Path $_.FullName
        if ($files.Count -gt 0) {
            $files | Compress-Archive -DestinationPath $NewDir\archcopy.zip
        }
    }

Чтобы запустить его в сценарии файла .bat, поместите приведенный выше код вфайл, такой как Archive-eFS_manual.ps1.Запустите его, используя:

powershell -NoProfile -File .\Archive-eFS_manual.ps1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...