Powershell 针对“问题”的解决方法&引用;具有延迟变量展开的For循环中的文本

Powershell 针对“问题”的解决方法&引用;具有延迟变量展开的For循环中的文本,powershell,batch-file,cmd,delayedvariableexpansion,Powershell,Batch File,Cmd,Delayedvariableexpansion,如何为for循环创建一个变通方法?问题是DelayedExpansion对于包含“!”的文件名失败 代码(这是更大脚本的一部分) 如果无法批量执行,如何在PowerShell中执行 可由原始批处理调用的内容,如: :FileScan Call %~dp0FileScanScript.ps1 IF %EpCount%==0 ( Echo. & Echo: No Episodes Found & GOTO :Err ) :FolderScan Call %~dp0FolderScan

如何为for循环创建一个变通方法?问题是DelayedExpansion对于包含“!”的文件名失败

代码(这是更大脚本的一部分)

如果无法批量执行,如何在PowerShell中执行 可由原始批处理调用的内容,如:

:FileScan
Call %~dp0FileScanScript.ps1
IF %EpCount%==0 ( Echo. & Echo: No Episodes Found & GOTO :Err )
:FolderScan
Call %~dp0FolderScanScript.ps1
编辑:调用集修复了原始代码,完全避免了延迟扩展

SET "EpCount=0"
FOR /f "Tokens=* Delims=" %%x IN ('Dir /b /o:n %~dp0*.mkv* *.mp4* *.avi* *.flv* 2^>nul') DO (
    SET /a "EpCount+=1"
    CALL SET "Ep%%EpCount%%=%%x"
)
注意:OP最初在问题上添加了标签,但后来删除了该标签(自恢复后)

以下批处理文件(
cmd
)循环的等效项:

SETLOCAL EnableDelayedExpansion
对于/f“Tokens=*Delims=“%%x IN('Dir/b/o:n%~dp0*.mkv**.mp4**.avi**.flv*2^>nul')DO(
设置/a“EpCount+=1”
设置Ep!EpCount!=%%x
)
PowerShell中(PSv3+)是:

#收集数组$Eps中的所有情节路径
$Eps=(Get ChildItem-递归$PSScriptRoot-包括*.mkv、*.mp4、*.avi、*.flv)。全名
#计算收集的路径数。
$EpCount=$Eps.Count
以上内容适用于嵌入
的路径实例。
$Eps
将是完整文件名的数组


然后逐个处理匹配的文件:

foreach($ep in$Eps){#循环所有文件(剧集)
#使用$ep
}
使用单个数组而不是不同的
$Ep1
$Ep2
。。。变量使得处理更加简单和高效


以上是逐个处理已收集的内存文件名的最快方法。
一种更高效(尽管速度稍慢)的基于管道的方法是:

Get ChildItem-Recurse$PSScriptRoot-Include*.mkv、*.mp4、*.avi、*.flv | ForEach对象{
#与$\一起使用。全名-自动变量$\表示手头的输入对象。
}
会适当地设置变量,就像

FOR /f "tokens=1*delims=[]" %%x IN (
 'Dir /b /o:n %~dp0*.mkv* *.mp4* *.avi* *.flv* 2^>nul ^|find /v /n ""'
 ) DO (
 SET /a epcount=%%x
 CALL SET ep%%x=%%y
)

(在每个名称前面加上
[num]
,然后使用
for
num
提取到
%%x
并将
name
提取到
%%y
(假设没有名称开始
[
]

最简单的解决方案确实是使用
set
引入另一个解析阶段:

setlocal DisableDelayedExpansion
pushd“%~dp0。”
设置/A“EpCount=0”
对于/F“delims=”%%x英寸('
目录/B/A:-D/O:N“*.mkv*”“*.mp4*”“*.avi*”“*.flv*”2^>nul
""做"(
设置/A“EpCount+=1”
调用集“Ep%%EpCount%%=%%x”
)
邻苯二胺
端部
但是,只要插入符号
^
出现在字符串或文件名中,就会出现问题,因为
call
在引用时会使它们加倍

要解决这个问题,您需要确保字符串也在第二个解析阶段展开,这可以通过使用临时变量来实现,如下所示:

setlocal DisableDelayedExpansion
pushd“%~dp0。”
设置/A“EpCount=0”
对于/F“delims=”%%x英寸('
目录/B/A:-D/O:N“*.mkv*”“*.mp4*”“*.avi*”“*.flv*”2^>nul
""做"(
设置“插曲=%%x”
设置/A“EpCount+=1”
呼叫集“Ep%%EpCount%%=%%集%%
)
邻苯二胺
设置Ep
端部
此外,我添加了过滤器选项
/A:-D
,以确保不返回任何目录。此外,我使用和临时更改为脚本的父目录。编写时的
dir
命令行搜索脚本父目录中的文件
*.mkv*
,但搜索当前工作目录中的所有其他文件,这可能不是您想要的


另一个选项是切换延迟扩展,这样当禁用延迟扩展时,
变量引用
%%x
将被扩展,当启用时,将完成对
Ep
数组样式变量的赋值。但您需要实施措施,将变量值传输到
endlocal
屏障之外,如以下示例所示:

setlocal DisableDelayedExpansion
pushd“%~dp0。”
设置/A“EpCount=0”
对于/F“delims=”%%x英寸('
目录/B/A:-D/O:N“*.mkv*”“*.mp4*”“*.avi*”“*.flv*”2^>nul
""做"(
此时禁用rem/*延迟扩展,因此扩展
rem变量引用`%%x`在这里是安全的:*/
设置“插曲=%%x”
设置/A“EpCount+=1”
rem//在此处启用延迟扩展:
setlocal EnableDelayedExpansion
rem/*使用只在赋值字符串上迭代一次的'for/F'循环,
rem不能为空,因此循环总是迭代;扩展值
rem存储在“%%%z”中,必须按顺序在“endlocal”之后分配
rem可在之后使用,且不会丢失感叹号:*/
对于/F“delims=“%%z in”(“Ep!EpCount!=!eption!”)执行以下操作(
端部
设置“%%z”
)
)
邻苯二胺
设置“Ep”
端部

wow这工作得更好,但是没有办法避免“[”和“]”,因为delims会导致我遇到的一些文件有这些漏洞,只能使用
findstr
,但这意味着将
delims
替换为
。但是,
tokens=1*
意味着只有围绕数字的
[]
会受到影响。
dir
输出行将是
[36]一些[name],包括[]
%%x
将获取第一个分隔符序列(忽略前导分隔符)之后的
36
%%y
所有内容,因此
%%y
将获取
一些[名称],包括[]
-只要它不是以
[
]开头即可。除了第一个字符以外的任何地方都是安全的。+1用于指出目录问题,同时在测试时我发现,似乎不仅
^
而且
%
都有问题,这对文件名中的
%
也有效吗?谢谢!是的,两者都有
CALL SET Ep%%EpCount%%=%%x
FOR /f "tokens=1*delims=[]" %%x IN (
 'Dir /b /o:n %~dp0*.mkv* *.mp4* *.avi* *.flv* 2^>nul ^|find /v /n ""'
 ) DO (
 SET /a epcount=%%x
 CALL SET ep%%x=%%y
)