我对批处理相当陌生,我的问题如下:
我有一长串文件夹,需要删除每个文件夹名称的前 3 个字符。想想 01_Folder1、02_Folder2、03_Folder3 等等。我尝试将在网上找到的 CMD 命令片段拼凑在一起,但无法想出一个可以完成我想要的操作的脚本。我什至尝试过使用 VBScript,因为我一般更熟悉 VB,但也未能找到解决方案。
有没有简单的方法可以解决这个问题?
编辑: 这是我的尝试;它给了我一个语法错误,但由于我对 CMD 不够熟悉,我真的不明白为什么:
setlocal enableextensions enabledelayedexpansion
for /d %%i in ("%~dp0*") do (set name=%%i && ren "!name!" "!name:~3!")
endlocal
FOR命令行不起作用,因为分配给循环变量i
是具有完整路径的目录名称,因此删除前三个字符会导致从目录路径中删除驱动器号、冒号和反斜杠,不是目录名称的前三个字符。此外,由于
name
和运算符
%%i
之间有空格,因此为环境变量
&&
分配了一个额外的空格。一种解决方案是:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
for /d %%i in ("%~dp0*") do set "name=%%~nxi" && ren "%%i" "!name:~3!"
endlocal
此解决方案的缺点是,由于启用了延迟扩展,名称或路径中带有一个或多个感叹号的目录名称无法正确处理,导致将完整目录名称中的!
解释为延迟扩展环境的开始/结束变量引用。另一个解决方案非常简单,只需使用命令行:
@for /D %%i in ("%~dp0*_*") do for /F "tokens=1* delims=_" %%j in ("%%~nxi") do @ren "%%i" "%%k"
外部 FOR 在批处理文件的目录中搜索与模式 *_*
匹配的非隐藏子目录。对于分配有循环变量完整路径的每个目录名称
i
,再使用一个FOR命令,该命令仅处理最后一个反冲之后的字符串(不带路径的目录名称)并将字符串拆分为子字符串(标记)。 字符串分隔符是使用选项
delims=_
定义的下划线。选项
tokens=1*
告诉FOR 根据 ASCII 表
将第一个下划线分隔字符串分配给指定的循环变量
j
,并将第一个下划线分隔字符串之后的一个或多个下划线后面的所有内容分配给下一个但一个循环变量
k
。
内部 FOR 将忽略第一个子字符串以分号开头的目录名称,作为默认的行结束符。但在这种情况下,没有目录的名称开头有 ;
。该命令行还存在一个问题。它不适用于 FAT32 或 exFAT 作为文件系统的驱动器,只是偶然在具有 NTFS 文件系统的驱动器上运行。原因是文件系统中的非隐藏目录列表发生变化,而外部
FOR 会迭代与模式匹配的目录条目。
更好的解决方案首先将要重命名的目录列表加载到 Windows 命令进程的内存中,该进程正在处理批处理文件,然后再开始重命名目录。
@for /F "delims=" %%i in ('dir "%~dp0*_*" /AD-H /B 2^>nul') do for /F "tokens=1* delims=_" %%j in ("%%i") do @ren "%~dp0%%i" "%%k"
在这种情况下,
FOR 在后台执行另一个命令进程,其中 %ComSpec% /c
和
'
中的命令行作为附加参数附加。所以在后台执行的是 Windows 安装到
C:\Windows
:
C:\Windows\System32\cmd.exe /c dir "C:\Batch\File\Path\*_*" /AD-H /B 2>nul
DIR 在批处理文件的目录中搜索
/AD-H
而非隐藏目录(属性目录且不隐藏)
*_*
/B
没有处理后台命令进程的STDOUT(标准输出)的路径。
使用命令重定向运算符的 Microsoft 文档,了解 2>nul
的说明。当 Windows 命令解释器在执行命令FOR
(执行嵌入的
>
命令行)之前处理此命令行时,重定向运算符
^
必须在 FOR 命令行上使用脱字符号 dir
进行转义,以便将其解释为文字字符使用在后台启动的单独命令进程。
FOR 处理批处理文件的 Windows 命令进程分别捕获写入后台命令进程的标准输出句柄的所有内容,并在启动后开始按上述方式处理它 cmd.exe
终止自身。因此,内存中已经存在一个目录名称列表,因此执行的REN 命令不会再导致在逐个处理时更改目录名称列表。 请注意,两个单行解决方案将名称为
01__Underscore_at_beginning
的目录重命名为
Underscore_at_beginning
而不是
_Underscore_at_beginning
。要了解所使用的命令及其工作原理,请打开
命令提示符窗口,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。
echo /?
endlocal /?
for /?
ren /?
set /?
setlocal /?