【问题标题】:Batch For Loop not separating string at specified delimiterBatch For Loop 不在指定分隔符处分隔字符串
【发布时间】:2019-01-04 06:26:42
【问题描述】:

我正在使用一个名为“Easy Context Menu”的程序,当您在文件资源管理器中单击鼠标右键时,它允许我创建自定义的上下文菜单。我想创建自己的上下文菜单项,允许我将文件及其父文件夹结构复制到另一个目录中,不包括父文件夹中的所有文件。

例子:

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

destination path: D:\cow

我希望将文件“bar.txt”和它的父文件夹复制到“大”目录中,而不将“大”或“富”中的其他文件复制到目录“牛”中。最终结果应如下所示:

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

'big' 应该只包含 'foo' 而 'foo' 应该只包含 'bar.txt'。该程序允许我将文件作为参数发送到我选择的文件,在本例中为批处理文件。

我在 ':main" 子程序中的 for 循环卡住了。它只会打印所选文件的整个路径并忽略分隔符。'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

最后我应该有多个变量,每个变量都是目标文件的父文件夹的名称,计数应该是有多少父文件夹,加上文件本身。我实际上得到的是一个变量,它仍然包含整个目标路径。

【问题讨论】:

  • 使用 setlocal enabledelayedexpansion 变量对于您的批处理文件是本地的,因此最后您还应该回显 !var1!" 而不是“全局”%var1% i> 也许这有帮助?
  • @StackingForHeap ! 仅在代码块内需要,%var1% 将在解析时进行评估。

标签: batch-file for-loop token


【解决方案1】:

for 循环没有像 tokens=* 那样定界, 它将所有令牌作为一个令牌。前导分隔符被剥离。 只有var0 有值,而不是回显的var1

要按路径段拆分_target,请使用:

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

您遇到的另一个问题是,如果您在 choice 提示符下选择 ngoto: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 移出标签循环。
  • 修复第一个参数检查(如果未定义)。

请参阅set /? 关于变量替换的信息,即"%_target:\=" "%",它将\ 替换为" "

【讨论】:

    猜你喜欢
    • 2021-10-06
    • 2014-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-25
    相关资源
    最近更新 更多