For loop For循环复制命令提示符中的文件,使用子字符串命名每个文件的目标(延迟扩展)

For loop For循环复制命令提示符中的文件,使用子字符串命名每个文件的目标(延迟扩展),for-loop,cmd,copy,substring,environment-variables,For Loop,Cmd,Copy,Substring,Environment Variables,我有一个文件目录和一个单独的目录,其中充满了文件夹,文件夹的名称对应于文件名的子字符串。我试图循环浏览一个文件列表,对于每个文件,如果有一个具有相应子字符串名称的文件夹,则将文件的副本放入其中。如果没有相应的文件夹,我需要忽略该文件。这不能在批处理文件中完成,需要在命令提示符下完成 我的问题是,对我命令的最初响应 for /f %I in ('dir /b J:\test\test_audio\en * ^| find ".wav"') do ( set var=I copy J:\test\t

我有一个文件目录和一个单独的目录,其中充满了文件夹,文件夹的名称对应于文件名的子字符串。我试图循环浏览一个文件列表,对于每个文件,如果有一个具有相应子字符串名称的文件夹,则将文件的副本放入其中。如果没有相应的文件夹,我需要忽略该文件。这不能在批处理文件中完成,需要在命令提示符下完成

我的问题是,对我命令的最初响应

for /f %I in ('dir /b J:\test\test_audio\en * ^| find ".wav"') do (
set var=I
copy J:\test\test_audio\en\%~I J:\test\test_designed_locations\%var:~0,5%\
)
是命令的语法不正确,我认为是由于命令的扩展顺序

....
C:\Windows\System32>(
set var=Ev164_en.wav
copy J:\test\test_audio\en\Ev164_en.wav J:\test\test_designed_locations\%var:~0,5%\
)
The syntax of the command is incorrect

C:\Windows\System32>(
set var=Ev178_en.wav
copy J:\test\test_audio\en\Ev178_en.wav J:\test\test_designed_locations\%var:~0,5%\
)
The syntax of the command is incorrect
...
这也解释了为什么第二次运行该命令会导致在所有命令中使用最后一个文件的子字符串,从而导致每个文件都存放在最后一个文件夹中,而其他文件夹中则没有

....
for /f %I in ('dir /b J:\test\test_audio\en * ^| find ".wav"') do (
set var=I
copy J:\test\test_audio\en\157_en.wav J:\test\test_designed_locations\Ev225\
)
    1 file(s) copied.
for /f %I in ('dir /b J:\test\test_audio\en * ^| find ".wav"') do (
set var=I
copy J:\test\test_audio\en\158_en.wav J:\test\test_designed_locations\Ev225\
)
    1 file(s) copied.
....
我怀疑我需要使用延迟扩展来停止正在处理的环境变量,并在使用之前覆盖彼此。我已经尝试在命令的开头添加setLocal enableDelayedExpansion,并将对变量的引用包装在bangs中

setLocal enableDelayedExpansion
for /f %I in ('dir /b J:\test\test_audio\en * ^| find ".wav"') do (
set var=%I
copy J:\test\test_audio\en\%~I J:\test\test_designed_locations\!var:~0,5!\
)
在逗号前加上或不加转义,我得到

....
C:\Windows\System32>(
set var=Ev164_en.wav
copy J:\test\test_audio\en\Ev164_en.wav J:\test\test_designed_locations\!var:~0,5!\
)
The syntax of the command is incorrect.
....
未处理变量的值。我开始怀疑是否真的有可能在一个命令中对所有文件进行for循环,并使用每个文件名的子字符串来标识将文件放在何处。非常感谢您的帮助

cmd /v /q /c "pushd "j:\test\test_audio\en" && ( for %a in (*.wav) do ( set "I=%~nxa" & if exist "!I:~0,5!\" copy "%a" "!I:~0,5!" ) & popd )"
只有在启用cmd实例的情况下启动它,才能从命令行使用延迟扩展

编辑以适应评论

pushd "j:\test\test_audio\en" && (for %a in (*.wav) do (set "I=%~nxa" & call pushd ^"%I:~0,5^%^" 2>nul &&(copy "%~fa" & popd)) & popd)

好的,这可以不用启动单独的cmd实例来启用延迟扩展,但是使用调用强制对该行进行第二次解析器求值所需的转义不是很明显。

谢谢@MC ND。参数启动cmd实例并启用延迟扩展?这在初始参数中没有提供给我,但可能是可用的。这是否意味着如果我不使用延迟扩展,这个问题就不可能在命令行中解决?这项工作是与其他人的程序集成,我在问题中列出的是他们给我的参数。“我现在想知道,在给定当前参数的情况下,是否有办法解决这个问题,或者我是否需要回去与另一个人重新协商。”gianthair,答案已更新。解析器删除代码块中的读取操作,并用变量中的值替换它们。如果变量在块内更改其值,则在删除读取操作时无法检索更改的值。您需要延迟扩展或对转义字符串使用call命令来强制进行第二次解析器求值。如果可以使用下划线分割文件名,还有另一种选择,使用一个传统的for/f来处理分割,但我不知道是否是这种情况。