Имена файлов .ZIP с пробелами некорректно работают при создании и распаковке пакета

Я закончил писать короткий пакетный сценарий, который автоматически распакует и удалит все заархивированные файлы в папке загрузок.

Я работаю отлично, за исключением случаев, когда представлены zip-файлы, в имени которых есть пробел.

Я не могу точно сказать, в чем проблема, поэтому я помещу здесь весь сценарий, поскольку он довольно короткий.

@echo off
setlocal
cd C:\Users\%username%\Downloads\
del /q search_result.txt


for /r %%i in (*.zip) do (
echo %%~nxi >> search_result.txt
)
for /f %%i in ("search_result.txt") do set asdf=%%~zi
if %asdf% gtr 0 (
goto unzipAgain
)
end
:unzipAgain
set /p zippedFile=< search_result.txt

Call :UnZipFile "C:\Users\%username%\Downloads\%zippedFile:~0,-4%" "C:\Users\%username%\Downloads\%zippedFile%"
exit /b

:UnZipFile <ExtractTo> <newzipfile>
cd /d %~dp0
set vbs = "%temp%\_.vbs"
if exist %vbs% del /f /q %vbs%
>%vbs%  echo Set fso = CreateObject("Scripting.FileSystemObject")
>>%vbs% echo If NOT fso.FolderExists(%1) Then
>>%vbs% echo fso.CreateFolder(%1)
>>%vbs% echo End If
>>%vbs% echo set objShell = CreateObject("Shell.Application")
>>%vbs% echo set FilesInZip=objShell.NameSpace(%2).items
>>%vbs% echo objShell.NameSpace(%1).CopyHere(FilesInZip)
>>%vbs% echo Set fso = Nothing
>>%vbs% echo Set objShell = Nothing
cscript //nologo %vbs%
if exist %vbs% del /f /q %vbs%

del C:\Users\%username%\Downloads\%zippedFile%
cd C:\Users\%username%\Downloads\
findstr /V %zippedFile% search_result.txt > newfile.txt
xcopy newfile.txt search_result.txt /y >nul
del newfile.txt /f /q >nul

for /f %%i in ("search_result.txt") do set asdf=%%~zi
if %asdf% gtr 0 (
goto unzipAgain
)

del search_result.txt 

ТИА, Эвин

n.b VBScript не мой, и я не знаю, как он работает, я просто использовал его вместе со своим собственным кодом.

Это большой объем кода для выполнения одной очень маленькой задачи. Я понимаю, что половина его используется для создания сценария VBscript, но все остальные строки кода пакетного файла можно свести к минимуму до нескольких строк. Если вы используете Windows 7 или более позднюю версию, я настоятельно рекомендую вам использовать Powershell для распаковки, поскольку это может быть буквально одна строка кода.

Squashman 26.10.2018 07:26

Я удивлен, что он также правильно работает с файлами, не содержащими пробелов! Попробуйте прочитать справку по команде For, (особенно UseBackQ и Tokens или Delims). Вы также должны научиться защищать строки, используя двойные кавычки, где это возможно.

Compo 26.10.2018 07:27

Я тестировал Vbscript с файлами, в имени которых были пробелы, и он работал нормально. Я не использовал ваш запутанный пакетный код.

Squashman 26.10.2018 07:51

Если вы собираетесь использовать Vbscript, я бы посоветовал вам переписать его, чтобы он принимал аргументы в скрипт при его запуске, вместо того, чтобы воссоздавать скрипт с переменными командного файла для каждого файла, который вам нужно обработать. Ваш текущий командный файл СУПЕР неэффективен. Не говоря уже о том, что вы совершаете непрерывные ВЫЗОВЫ, никогда не возвращаясь к родительскому процессу, прежде чем сделать еще один ВЫЗОВ.

Squashman 26.10.2018 08:17

Не уверен, почему вы используете FOR /R, потому что ваш сценарий никогда не будет обрабатывать zip-файл в подпапке текущего каталога. Если вы просто обрабатываете файлы в одной папке, опция /R вам не нужна.

Squashman 26.10.2018 08:19
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
163
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Честно говоря, я не могу сказать, что в своих самых смелых мечтах я бы попытался закодировать то, что вы сделали вот так. Вы буквально сделали гору из кротового холма. Вы не могли бы усложнить себе жизнь. Думаю, как только вы увидите эти три примера кода, вы поймете, почему вам следует придерживаться K.I.S.S. принцип.

Код Vbscript, который у вас есть, отлично работает с пробелами. Вероятно, что-то было в коде вашего командного файла, что-то напортачило. Вы можете значительно упростить свой код, используя одну единственную команду FOR и просто создав Vbscript один раз. Я изменил VBscript, чтобы он принимал аргументы командной строки.

@echo off
set "source=C:\Batch\unzip"
CD /D "%source%"
call :createVBS "unzip.vbs"

FOR %%G IN (*.zip) DO (
    cscript //nologo "%vbs%" "%source%\%%~nG" "%source%\%%~G"
    del "%%~G"
)
del "%vbs%" 2>nul
exit /b

:CreateVBS
set "vbs=%~1"
del "%vbs%" 2>nul
>%vbs%  echo Set fso = CreateObject("Scripting.FileSystemObject")
>>%vbs% echo Set objArgs = WScript.Arguments
>>%vbs% echo If NOT fso.FolderExists(objArgs(0)) Then
>>%vbs% echo fso.CreateFolder(objArgs(0))
>>%vbs% echo End If
>>%vbs% echo set objShell = CreateObject("Shell.Application")
>>%vbs% echo set FilesInZip=objShell.NameSpace(objArgs(1)).items
>>%vbs% echo objShell.NameSpace(objArgs(0)).CopyHere(FilesInZip)
>>%vbs% echo Set fso = Nothing
>>%vbs% echo Set objShell = Nothing

Powershell отсутствует около 10 лет назад. С тех пор было несколько способов распаковать файлы в Powershell. Эта первая версия будет работать, если вы используете версию Powershell до версии 5.

@echo off
set "source=C:\Batch\unzip"
CD /D "%source%"

for %%G in (*.zip) do (
    powershell -command "Add-Type -AssemblyName System.IO.Compression.FileSystem;[System.IO.Compression.ZipFile]::ExtractToDirectory('%%~G', '.\%%~nG')"
    del "%%~G"
)

В версии 5 Powershell код был значительно упрощен с помощью нового командлета.

@echo off
set "source=C:\Batch\unzip"
CD /D "%source%"

for %%G in (*.zip) do (
    powershell Expand-Archive '%%~G' -DestinationPath '.\%%~nG'
    del "%%~G"
)

Итак, вы можете видеть, как обращение к Powershell значительно сократило объем кода, который вам нужен в вашем пакетном файле.

Другие вопросы по теме