Создание пакетного файла - в зависимости от переменной, поиск типа файла и извлечение или перемещение

Пытался создать дополнительный пакетный скрипт, который обрабатывает файлы для меня. Я получаю либо один, либо несколько тестовых файлов .pdf в файле .rar.

Итак, к чему я пытаюсь стремиться:

If the first variable 1 is named 'test' then
    Is there a .rar file in the folder from variable 2 then
        Extract to a folder and then delete .rar file
    else
        check that there is a .pdf file and then copy to folder
Else
    Tell the user that neither a file or a archive has been found

Мне удалось собрать это вместе, но мне нужна помощь, чтобы попытаться расширить его, чтобы включить все варианты:

@echo off
set "cat=%1"
IF "%cat%"=="test" ( for /f %%G in ('dir *.rar /b') do set filename=%%~G)

echo %filename%

Это дает мне только половину имени файла, так как в имени файла есть пробелы, также нужно изменить каталог в 3-й строке, чтобы искать в отправленной переменной 2.

Чтобы добавить к этому, мне только что сказали, что то же самое для файлов .txt, множители отправляются мне в файле .rar.


person madmiddle    schedule 12.12.2019    source источник
comment
Команда FOR /F отделяет вывод от предложения IN, используя пробел в качестве разделителя. Поэтому, если вы хотите продолжать использовать этот код, вы должны использовать параметр delimis, чтобы указать команде FOR /F не использовать какие-либо разделители: "delims=". Но вместо этого вы можете просто использовать базовую команду for: FOR %%G IN (*.rar) do set filename=%%G   -  person Squashman    schedule 12.12.2019


Ответы (2)


Я предлагаю открыть командную строку, запустить call /? и прочитать справку. В справке объясняется, как на аргументы (также называемые опциями или параметрами, но не переменными) пакетного файла можно ссылаться из пакетного файла.

Рекомендуется проверять, вызывается ли пакетный файл хотя бы с одним аргументом, должен ли он вызываться хотя бы с одним аргументом, и выводить справку для корректного использования пакетного файла, если он был запущен без какого-либо аргумента или если он был запущен с /?, который используется по умолчанию в Windows для получения справки о команде или программе.


Руководство для консольной версии WinRAR находится в файле Rar.txt в папке программных файлов WinRAR. В этом текстовом файле после его открытия двойным щелчком можно прочитать, что Rar.exe может извлечь один или несколько архивных файлов *.rar, найденных в каталоге. По этой причине нет необходимости использовать команду FOR. Но для этой задачи рекомендуется использовать команду FOR, так как файл(ы) RAR следует удалить после успешного извлечения архива(ов) RAR.


Давайте посмотрим на командную строку FOR for /f %%G in ('dir *.rar /b') do и на то, что она делает при выполнении.

ДЛЯ с параметром /F для обработки содержимого текстового файла или отдельной строки или вывода командной строки в этом случае приводит к запуску командного процесса в фоновом режиме с %ComSpec% /c и командной строкой между двумя добавленными ' . Таким образом, командный процесс Windows cmd.exe, обрабатывающий пакетный файл с помощью for /F, выглядит следующим образом, когда Windows установлена ​​в C:\Windows по умолчанию:

C:\Windows\System32\cmd.exe /c dir *.rar /b

Команда DIR выполняется отдельным командным процессом в фоновом режиме.

  • поиск в текущем каталоге
  • для записей каталога (файлов или каталогов)
  • соответствие шаблону подстановки *.rar
  • и не имея скрытого набора атрибутов (неявное значение по умолчанию — /A-H для опции /A вообще не указано)
  • и выводит для обработки STDOUT найденные записи каталога, соответствующие указанным выше критериям, в чистом формате построчно, что означает только имя файла/папки без пути и никогда не заключенное в двойные кавычки, даже если они содержат пробел или один из эти символы &()[]{}^=;!'+,`~.

Сообщение об ошибке выводится DIR для обработки STDERR фонового командного процесса, если он не может найти ни одной записи каталога, соответствующей критериям поиска.

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

FOR, используемый с параметром /F, всегда игнорирует пустые строки. Здесь это не имеет значения, потому что DIR не выводит пустые строки при выполнении с параметром /B.

for /F по умолчанию разбивает непустую строку на подстроки, используя обычный пробел и горизонтальную табуляцию в качестве разделителей строк, и по умолчанию назначает только первую строку, разделенную пробелом/табуляцией, указанной переменной цикла, которая здесь является переменной цикла G. for /F по умолчанию дополнительно игнорирует обработанную строку, если первая подстрока после разделения строки начинается с точки с запятой, потому что eol=; является параметром по умолчанию для конца строки.

Таким образом, командная строка for /f %%G in ('dir *.rar /b') do вызывает несколько проблем при обработке списка записей каталога, выводимого DIR.

  1. Для имени файла/папки, содержащего пробел, только первая часть имени файла/папки, разделенная пробелом/табуляцией, назначается переменной цикла G вместо полного имени. Например, имя типа My Archive.rar приводит к тому, что переменной цикла G присваивается только My.
  2. Имя файла/папки с одним или несколькими начальными пробелами назначается переменной цикла G без этих начальных пробелов, что снова означает, что G не содержит полного имени. Например, имя типа   TwoLeadingSpaces.rar приводит к назначению переменной цикла G просто TwoLeadingSpaces.rar без двух начальных пробелов, а файл (или папка) не найден при ссылке на значение переменной цикла G.
  3. Имя файла/папки с точкой с запятой в начале после нуля или более начальных пробелов полностью игнорируется командой FOR для дальнейшей обработки. Например, такие имена, как ;Test.rar (имя, начинающееся с точки с запятой) или  ;TestWithALeadingSpace.rar (имя с начальным пробелом и точкой с запятой), полностью игнорируются для дальнейшей обработки FOR.

Пункты 2 и 3 обычно не вызывают проблем, так как имена файлов/папок с начальным пробелом или точкой с запятой в начале действительно очень редки. А вот имя файла/папки с пробелом встречается очень часто.

Решением будет использование FOR без опции /F:

for %%G in (*.rar) do

FOR теперь сам ищет не скрытые файлы (не каталоги) в текущем каталоге, соответствующем шаблону подстановки *.rar, и присваивает найденное имя файла без пути переменной цикла G и далее запускает команды после do. Не запускается дополнительный командный процесс и не выполняется разделение подстроки.

Но есть проблема с этим очень простым решением в случае, если команды, выполняемые для каждого найденного имени файла, удаляют, перемещают или переименовывают файлы, соответствующие шаблону подстановки *.rar. Список записей каталога, соответствующих подстановочному шаблону, изменяется на каждой итерации тела цикла FOR, в то время как команда FOR запрашивает записи каталога одну за другой с выполнением команд между ними. каждый запрос каталога. Это особенно проблематично для дисков FAT16, FAT32 и exFAT, но также может привести к неожиданному поведению на дисках NTFS.

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

Таким образом, лучшим решением для этой задачи с требованием удалить файл архива RAR после успешного извлечения является:

for /F "eol=| delims=" %%I in ('dir *.rar /A-D /B 2^>nul') do

Параметр DIR /A-D приводит к игнорированию записей каталога с атрибутом directory. Таким образом, вывод DIR — это просто имена файлов, соответствующие шаблону подстановки в текущем каталоге, включая скрытые архивные файлы RAR.

2^>nul передается как 2>nul фоновому командному процессу, что приводит к перенаправлению сообщения об ошибке, выводимого DIR при отсутствии найденного файла *.rar, на устройство NUL для его подавления.

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

Опция for /F eol=| изменяет символ конца строки с ; на |. Ни одно имя файла не может иметь вертикальную черту в имени файла в соответствии с документацией Microsoft о Именование файлов, путей и пространств имен. Таким образом, ни одно имя файла больше не игнорируется FOR из-за опции конца файла.

Параметр for /F delims= изменяет список разделителей для разделения строки на подстроки на пустой список разделителей, что полностью отключает поведение разделения строки. Таким образом, имя файла с одним или несколькими пробелами в любом месте имени файла полностью присваивается указанной переменной цикла I.


Описание задачи не очень ясно относительно того, что делать в зависимости от аргументов пакетного файла, особенно если первый аргумент не чувствителен к регистру test.

Однако следующий закомментированный пакетный файл может работать для этой задачи при вызове с первым аргументом, равным test, или вообще без аргументов, или с /? в качестве первого аргумента.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if "%~1" == "" goto OutputHelp
if "%~1" == "/?" goto OutputHelp
if /I not "%~1" == "test" goto MoreCode

set "SourceFolder=%~2"
if defined SourceFolder goto CheckFolder

echo/
echo Error: Folder with RAR or PDF file(s) not specified on command line.
goto OutputHelp

:CheckFolder
rem Replace all forward slashes by backslashes in folder name.
set "SourceFolder=%SourceFolder:/=\%"
rem Append a backslash to folder path if it does not end with a backslash.
if not "%SourceFolder:~-1%" == "\" set "SourceFolder=%SourceFolder%\"
rem Check the existence of the source folder.
if exist "%SourceFolder%" goto ProcessFolder

echo/
echo Error: Folder "%SourceFolder%" does not exist.
goto OutputHelp

:ProcessFolder
rem Get full qualidfied folder name, i.e. the folder name
rem with its absolute path and ending with a backslash.
for %%I in ("%SourceFolder%") do set "SourceFolder=%%~fI"

rem Define the destination folder for the PDF files extracted from the
rem RAR archive file(s) in source folder or copied from source folder.
set "DestinationFolder=C:\Temp\Test\"

rem Search for all *.rar files in folder passed with second argument and
rem extract all *.pdf files in each RAR archive file to the configured
rem destination folder. Rar.exe creates the destination folder automatically
rem if it is not already existing. The batch file is halted after processing
rem a RAR file on which Rar.exe exited with a value greater 0. Read the exit
rem codes documentation of Rar.exe at bottom of text file Rar.txt for more
rem information about the RAR exit codes. See Rar.txt also for the meaning
rem of the few RAR switches used here.

set "RarFileCount=0"
for /F "eol=| delims=" %%I in ('dir "%SourceFolder%*.rar" /A-D /B 2^>nul') do (
    set /A RarFileCount+=1
    "%ProgramFiles%\WinRAR\Rar.exe" e -cfg- -idcdp -or -- "%SourceFolder%%%I" *.pdf "%DestinationFolder%"
    if not errorlevel 1 (del /A /F "%SourceFolder%%%I") else echo/& pause
)

if %RarFileCount% == 0 goto CheckFiles
if %RarFileCount% == 1 (set "PluralS=") else set "PluralS=s"
echo/
echo Info: Processed %RarFileCount% *.rar file%PluralS% in folder "%SourceFolder%".
goto EndBatch

:CheckFiles
echo Info: There are no *.rar files in folder "%SourceFolder%".
if exist "%SourceFolder%*.pdf" goto CopyFiles

echo Info: There are no *.pdf files in folder "%SourceFolder%".
goto EndBatch

:CopyFiles
rem Copy all PDF files in source folder to destination folder. xcopy.exe
rem creates destination folder automatically if it is not already existing.
echo/
%SystemRoot%\System32\xcopy.exe "%SourceFolder%*.pdf" "%DestinationFolder%" /C /I /Y
goto EndBatch

:OutputHelp
echo/
echo Usage: %~n0 [TEST] [Folder with RAR or PDF file(s)]
echo/
echo    If the first argument is case-insensitive TEST, the second argument
echo    specifies the folder containing the RAR files to extract or the PDF
echo    files to copy to destination folder. The folder must be specified
echo    with first argument being TEST.
echo/
pause
goto EndBatch

:MoreCode
rem Add here the code to execute on first argument is not case-insensitive TEST.

:EndBatch
endlocal

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

  • call /?
  • del /?
  • dir /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • pause /?
  • rem /?
  • set /?
  • setlocal /?
  • xcopy /?
  • "%ProgramFiles%\WinRAR\Rar.exe" /?
person Mofi    schedule 14.12.2019

Вы можете использовать это:

@echo off
set "cat=%~1"
IF "%cat%"=="test" ( 
  for %%G in (*.rar) do set filename=%%G
)
echo %filename%

Здесь подстановочный знак используется для получения всех файлов rar в каталоге.

person programmer365    schedule 14.12.2019