Powershell 针对“问题”的解决方法&引用;具有延迟变量展开的For循环中的文本
如何为for循环创建一个变通方法?问题是DelayedExpansion对于包含“!”的文件名失败 代码(这是更大脚本的一部分) 如果无法批量执行,如何在PowerShell中执行 可由原始批处理调用的内容,如: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
: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
)