Пакет для цикла не разделяет строку в указанном разделителе - PullRequest
0 голосов
/ 04 января 2019

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

Пример:

target file path: C:\the\big\foo\bar.txt

destination path: D:\cow

Я хочу, чтобы файл «bar.txt» и его родительские папки вплоть до «большого» копировались в каталог «корова» без других файлов в «большом» или «foo».Конечный результат должен выглядеть следующим образом:

D:\cow\big\foo\bar.txt

'big' должен содержать только 'foo', а 'foo' должен содержать только 'bar.txt'.Программа позволяет мне отправить файл в качестве параметра в файл по моему выбору, в данном случае это командный файл.

Я застрял в цикле for в подпрограмме ': main'. Это будет толькопечатать весь путь выбранного файла и игнорирует разделитель. 'countA' возвращается как '1' после цикла, и он напечатал бы весь путь минус буква диска. Я не понимаю, почему цикл for игнорирует разделитель ине разделяя путь на отдельные имена папок. Причина, по которой я пытаюсь это сделать, заключается в том, что пользователь может выбирать, в какой момент следует копировать родительские папки.полностью понимать 'setlocal' и некоторые другие вещи.

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

@echo off
setlocal
set _target=""
set _dest=""
if not exist %1 goto:error_no_path
set _target=%~pnx1
echo %_target%
goto :dest_selct

:dest_selct
echo select destination folder
pause
set "psCommand="(new-object -COM 'Shell.Application')^
.BrowseForFolder(0,'Please choose destination folder.',0,0).self.path""

for /f "usebackq delims=" %%I in (`powershell %psCommand%`) do set "folder=%%I"

setlocal enabledelayedexpansion
echo You chose %folder%
choice /c ync /n /m "Is this correct? ([Y]es, [N]o, [C]ancel)"
if %ERRORLEVEL% EQU 3 goto:eof
if %ERRORLEVEL% EQU 2 goto:dest_selct
if %ERRORLEVEL% EQU 1 (set _dest="%folder%")&&(goto:main)

:error_no_path
ECHO No file path/name
pause
GOTO:eof

:main
echo main
set _countA=0
echo count starts at %_countA%
for /f "tokens=* delims=\" %%F in ("%_target%") do (
    echo token %_countA% is %%F
    echo count is %_countA%
    set var!_countA!=%%F
    set /a countA+=1
)
echo var1: %var1%
echo count is now %countA%
pause

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

1 Ответ

0 голосов
/ 04 января 2019

Цикл for не разделяет, поскольку у вас есть tokens=*, который получает все токены как один токен.Ведущие разделители лишены.Значение имеет только var0, а не повторяемое var1.

Чтобы разделить _target по сегментам пути, используйте:

for %%F in ("%_target:\=" "%") do echo %%~F

Еще одна проблема, если вы выбираете n в приглашении choice, goto:dest_selct заставит setlocal enabledelayedexpansion выполнить снова.Поскольку вы не используете endlocal, локальная среда повторяется без конца.Иногда подразумевается endlocal, поэтому вам может не понадобиться его использовать, хотя и не в этом случае.

Попробуйте это исправить:

@echo off
setlocal
set "_target="
set "_dest="
if not exist "%~1" goto:error_no_path
set "_target=%~pnx1"
echo %_target%
goto :dest_selct

:dest_selct
echo select destination folder
pause
set "psCommand="(new-object -COM 'Shell.Application')^
.BrowseForFolder(0,'Please choose destination folder.',0,0).self.path""

for /f "usebackq delims=" %%I in (`powershell %psCommand%`) do set "folder=%%I"

echo You chose %folder%
choice /c ync /n /m "Is this correct? ([Y]es, [N]o, [C]ancel)"
if %ERRORLEVEL% EQU 3 goto:eof
if %ERRORLEVEL% EQU 2 goto:dest_selct
if %ERRORLEVEL% EQU 1 (set "_dest=%folder%") && goto:main

:error_no_path
ECHO No file path\name
pause
GOTO:eof

:main
setlocal enabledelayedexpansion
echo main
set "countA=0"
echo count starts at %countA%

rem Remove leading backslash if exist.
if "%_target:~,1%" == "\" set "_target=%_target:~1%"

rem Split into path segments.
for %%F in ("%_target:\=" "%") do (
    echo token !countA! is %%~F
    echo count is !countA!
    set "var!countA!=%%~F"
    set /a countA+=1
)

echo var1: %var1%

rem Echo all variables starting with var and their values.
set var
echo count is now %countA%
endlocal
pause
  • Скорректировано двойное цитирование.
  • Изменены экземпляры имени переменной от _countA до countA для соответствия.
  • set var для отображения всех переменных, начинающихся с var для отладки.
  • forцикл теперь распадается на сегменты пути.
  • Перемещено setlocal enabledelayedexpansion из цикла метки.
  • Исправлена ​​проверка 1-го аргумента, если она не определена.

См. set /?о подстановке переменных, т.е. "%_target:\=" "%", которая заменяет \ на " ".

...