【问题标题】:Batch: rename all the files and subfolders批处理:重命名所有文件和子文件夹
【发布时间】:2011-12-26 23:00:06
【问题描述】:
for /f "tokens=*" %%f in ('dir /ad /s /b "C:\Users\Tin\Desktop\renameFolders"') do (
setlocal enabledelayedexpansion enableextensions
  set N=%%f
  set N=!N: =_!
  ren "%%f" "!N!"
)

如何重命名所有文件和子文件夹? 我未能遍历并重命名所有子文件夹。

文件结构: 测试:

file 2.txt
file 1.txt
folder 1
test.bat

文件夹 1:

folder 2
file 3.txt

文件夹 2: 文件 4.txt

【问题讨论】:

标签: loops batch-file rename


【解决方案1】:

在我看来你有三个问题:

  1. 使用 /ad 开关意味着您将只处理目录而不是文件
  2. set N=%%f 将导致 N 获取包括路径在内的全名,因为这是 dir /b 返回的内容
  3. 需要反转递归。如果您将“文件夹 1”重命名为“文件夹 1”,那么当您检查“文件夹 1/文件夹 2”时,路径不再有效。

修复 (1) 只是删除 /ad 修复(2)是使用set N=%%~nxf 我还不确定如何修复#3。我偶然发现重复运行固定(1)和(2)的脚本最终会重命名所有文件。但我确信那里有更好的答案。

【讨论】:

  • 名称必须包含完整路径;否则,如何定位第一级以下的文件/文件夹?或者如果批处理文件是在不同的目录中启动的,则在任何级别?
  • setlocal EnableDelayedExpansion EnableExtensions FOR /F "delims=" %%D IN ('DIR /b /s /ad') DO ( SET "old=%%D" SET new=!old: = _! ​​if not !new! == !old!ren "!old!" "!new!" ) 暂停
    我的代码有什么问题?
  • 我能问更多关于第一部分的信息吗? pushd和popd有什么用?它是否存储当前目录?并调用 renameFile 函数?和弹出?并退出脚本?不知道第一部分...请解释一下。谢谢。
  • @Aacini - rename 命令有两个参数,原始文件名(带路径)和新文件名。新的文件名部分不应该有路径。
  • 但是你认为新文件名中不应该出现的路径在哪里?
【解决方案2】:

这里的问题是必须完成文件夹重命名的顺序。最深的文件夹必须首先重命名,并且重命名过程必须向上进行,直到到达顶层文件夹。这样做的唯一方法是通过递归子例程以这种方式处理每个现有文件夹:

Rename the files in this folder.
For each folder in this folder:
    Process it recursively.
    Rename it.

另外,请注意,并非所有文件/文件夹都必须重命名,只有名称中有空格的文件/文件夹;否则 REN 命令会发出错误。下面的批处理文件将第一个参数作为要处理的顶级文件夹:

@echo off
setlocal EnableDelayedExpansion EnableExtensions
pushd %1
call :ProcessThisFolder
popd
exit /b

:ProcessThisFolder
REM Rename the files in this folder.
for %%f in (*.*) do (
    set "old=%%f"
    set new=!old: =_!
    if not !new! == !old! ren "!old!" "!new!"
)
REM For each folder in this folder:
for /D %%d in (*) do (
    REM Process it recursively.
    cd %%d
    call :ProcessThisFolder
    cd ..
    REM Rename it.
    set "old=%%d"
    set new=!old: =_!
    if not !new! == !old! ren "!old!" "!new!"
)

编辑

原始方法的问题是执行重命名的顺序。假设dir /s /b ...的结果是:

C:\Users\Tin\Desktop\renameFolders\file 1.txt
C:\Users\Tin\Desktop\renameFolders\file 2.txt
C:\Users\Tin\Desktop\renameFolders\folder 1
C:\Users\Tin\Desktop\renameFolders\folder 1\file 3.txt
C:\Users\Tin\Desktop\renameFolders\folder 1\folder 2

当第 3 行被处理时,folder 1 被重命名为folder_1,所以此时第 4 行和第 5 行中的名称不再有效。第一次重命名必须在file 3.txtfolder 2 上完成,然后向上到上面的文件夹,但dir 命令显示的行按字母顺序排序,其他可用的顺序在这种情况下没有帮助。

上面程序的第一部分是这样工作的:

pushd %1                 Save current directory and do a CD %1
call :ProcessThisFolder  Call the subroutine defined in this same file below
popd                     Do a CD to the directory saved by previous PUSHD
exit /b                  Terminate here this Batch file; otherwise the lines
. . .                    below would be executed again

您可以通过使用 /? 来查看任何命令的操作?参数,例如:pushd /?

【讨论】:

  • CD%1 与 cd %%d 在路径方面是否相同(或者如您所说,它有助于进入最深的目录来完成 dir 无法完成的工作?)?而且,如果我们 pushd %1 (路径应该是我放置 bat 文件的位置),然后在调用 :ProcessThisFolder 之后(它通过使用“cd %%d”和“cd ..”循环整个目录呢? ,然后它返回到 %1 目录。是这样吗?因为我总是对 BATCH 中的路径问题感到困惑。
  • 是的,您的描述是正确的。在子例程中,我们也可以使用pushd %%dpopd 而不是cd %%dcd ..,但在这种情况下,我们确定每个文件夹都比上一个文件夹低一级,因此不需要pushdpushd 用于当我们不知道当前目录在哪里并想稍后返回时使用。
猜你喜欢
  • 2022-08-10
  • 2016-09-11
  • 2016-03-26
  • 2011-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-02
  • 2018-12-23
相关资源
最近更新 更多