【问题标题】:Batch file variables in a for loopfor循环中的批处理文件变量
【发布时间】:2013-08-08 01:34:32
【问题描述】:

我很难理解循环批处理文件中的变量。当我认为我搞砸了时,我发现了一个例子,它没有按我的预期工作,我觉得我一直在绕圈子......

我已经编写了我的全部代码,以防它有所作为,基本上我有一个包含许多子文件夹的存档文件夹,我想检查我的上传数据(将在末尾移动到存档文件夹脚本 - 当我让这部分工作时编写)已经被处理。如果是这样,请移至带有日期的 Duplicates 文件夹:

 @echo off

 for /F "usebackq tokens=1,2 delims==" %%i in (`wmic os get LocalDateTime /VALUE 2^>NUL`) do if '.%%i.'=='.LocalDateTime.' set localDT=%%j
 set localYYYY=%localDT:~0,4%
 set localMM=%localDT:~4,2%
 set localDD=%localDT:~6,2%
 set localDate=%localYYYY%-%localMM%-%localDD%
 set localTime=%localDT:~8,2%:%localDT:~10,2%

 for %%f in ("C:\Test\837Store\*.837") DO if exist /R "C:\Test\Archive\%%~nxf" (
     set VariableTemp=%%~nxf
     echo %VariableTemp%
     IF NOT EXIST "C:\Test\Archive\Duplicates" mkdir "C:\Test\Archive\Duplicates"
     IF NOT EXIST "C:\Test\Archive\Duplicates\%localYYYY%" mkdir "C:\Test\Archive\Duplicates\%localYYYY%"
     IF NOT EXIST "C:\Test\Archive\Duplicates\%localYYYY%\%localMM%" mkdir "C:\Test\Archive\Duplicates\%localYYYY%\%localMM%"
     copy "%%~nxf" "C:\Test\Archive\Duplicates\%localYYYY%\%localMM%"
     echo %localDate% %localTime%        Duplicate claims file: %%~dpnxf File moved to archive     >> "C:\Test\Log\Error.log"
 )
 pause

我的问题是,变量 %%f 似乎没有通过循环设置。 mkdir 命令已运行,但是当我们到达副本时出现“找不到文件”错误。为了尝试查看发生了什么,我包含了 VariableTemp 并根据代码进行设置,希望看到文件的名称和扩展名。相反,我的回声正在打印“%~nxf”

谁能帮我理解这些变量是如何工作的?为什么我看不到 837Store 中的文件名?

只是为了补充信息,我在 C:\Test\837Store 中有以下 2 个文件:

1.837 2.837

我在 C:\Test\Archive\2013\08 中有相同的 2 个文件,因此希望它们从 837Store 移动到相关的 Duplicates 文件夹。

谢谢。

【问题讨论】:

  • Endoro 已经解决了这个问题,但是有几个 cmets:您将 "%~nxf" 视为 VariableTemp 的值这一事实表明之前的运行已将 VariableTemp 设置为该值。与大多数语言不同,批处理继承了在同一 cmd 会话中运行的先前程序的变量。批处理程序所做的任何更改都将保留在原地,直到再次特别更改 - 除非在 setlocal 和 endlocal(或文件结束/程序)之间进行更改,此时环境恢复到其状态当setlocal 被执行时。
  • 下一期是风格问题。 IF NOT EXIST "dirname" 肯定有效,但md "dirname" 2>nul 将创建一个目录,如果它不存在,2>nul 会转储“它已经存在”消息。将这个INSIDE 放在循环中没有什么意义,因为目标目录名称在循环中不会改变。 md/mkdir(它们是同义词)应该移出循环 - 在 FOR 之前 - 完成一次,而不是(可能)多次。最后,IF EXIST /R 名义上不是有效的语法。它的目的是什么?
  • 感谢您的提示!我添加 /R 的原因是因为没有它,脚本似乎不会遍历子文件夹 - “Duplicates”文件夹是使用 /R 创建的,但如果我删除它则不会。老实说,我更多地使用反复试验而不是正确理解来构建它,所以这些答案非常棒。谢谢!

标签: for-loop batch-file environment-variables


【解决方案1】:
@ECHO OFF
SETLOCAL

for /F "usebackq tokens=1,2 delims==" %%i in (`wmic os get LocalDateTime /VALUE 2^>NUL`) do if '.%%i.'=='.LocalDateTime.' set localDT=%%j
set localYYYY=%localDT:~0,4%
set localMM=%localDT:~4,2%
set localDD=%localDT:~6,2%
set localDate=%localYYYY%-%localMM%-%localDD%
set localTime=%localDT:~8,2%:%localDT:~10,2%

mkdir "U:\Test\Archive\Duplicates\%localYYYY%\%localMM%" 2>nul


for /R U:\Test\837Store %%f in (*.837) DO ECHO processing %%~ff&if exist "U:\Test\Archive\%%~nxf" (
 IF EXIST "u:\Test\Archive\Duplicates\%localYYYY%\%localMM%\%%~nxf" (
  echo %localDate% %localTime%        Duplicate claims file: %%~dpnxf File ALREADY DUPLICATED   >> "u:\Error.log"
 ) ELSE (
  MOVE "%%~ff" "u:\Test\Archive\Duplicates\%localYYYY%\%localMM%"
  echo %localDate% %localTime%        Duplicate claims file: %%~dpnxf File moved to archive     >> "u:\Error.log"
 )
)
rmdir "U:\Test\Archive\Duplicates\%localYYYY%\%localMM%" 2>nul
rmdir "U:\Test\Archive\Duplicates\%localYYYY%" 2>nul
rmdir "U:\Test\Archive\Duplicates" 2>nul
GOTO :EOF

这是我的解释。

我已使用我的 RAMdrive 进行测试,因此需要更改驱动器号,以及错误日志位置。

我已经为重复存在添加了一个额外的测试 - 只是报告这种情况。

我已将您的 COPY 更改为 MOVE 以匹配您的叙述。无论哪种方式,如果您希望禁止显示“已复制/移动 1 个文件”消息,附加到命令的 >nul 应禁止显示。

MD/MKDIR 将在目标上方创建任何必要的子目录。

末尾的三个 'rmdir/RD`s 旨在删除任何具有目标名称的空子目录。

【讨论】:

  • 再次感谢彼得的帮助!不幸的是,我仍然遇到同样的“找不到指定的文件”错误。由于 .837 文件未被复制,因此会创建 Duplicates 文件夹,然后将其删除。事实上,error.log 文件正在打印“重复声明文件:%~dpnxf 文件已移至存档”行 - 对我来说,就好像没有按照我原来的问题设置变量,否则我们应该得到文件路径和名称在那里,对吧?这是否可能存在一些安全或权限问题?
  • 只是附加注释,该变量在 for 循环的第一行起作用,只是由于某种原因似乎不在其中。我在终端中得到的输出是:“processing C:\Test\837Store\1.837”“processing C:\Test\837Store\2.837”“系统找不到指定的文件”
  • 哎哟!这非常令人费解。我提供的代码是直接从我的测试设置中粘贴的,它看起来运行良好。也许是一些基本问题 - 批处理对布局和空间位置有些敏感。像NOTEPAD 这样的编辑器有时会尝试以一种奇怪的方式重新格式化批次。最好复制粘贴到像editplus 这样的适当编辑器中。 Batch 在很大程度上不区分大小写 MAJOR EXCEPTION 是 for 循环元变量 %%f (在您的情况下)。最后,您确定您已正确修改了所有u: 实例吗?
  • 但是这些都不应该呈现您在日志文件中报告的%~dpnxf 文本 - 所以,有点神秘。实际上,ECHO processing %%~ff 是我省略的一段剩余测试代码。您可以通过在 FOR/R 行之前的新行上添加 @echo on 并在最后一个右括号行之前的新行上添加“暂停”来更好地了解正在发生的事情。这应该清楚地显示程序正在做什么。
  • 感谢您的帮助@Peter。我仍然没有得到想要的结果,但我看到了一些非常奇怪的东西。我已经仔细检查了linkeditplus 中的间距问题,并且所有 u: 实例都已清除。当按照您的建议放置 echo 和 pause 命令时,我看到了一些非常奇怪的东西:处理 1.837,处理 2.837 IF EXIST ... ELSE ... - 我希望看到处理 1.837,IF EXIST ... ELSE。 .. 处理 2.837, IF EXIST... ELSE... 就好像 for 没有在顶行之外循环,尽管我的括号设置正确 - 知道为什么吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
相关资源
最近更新 更多