【问题标题】:Batch command to delete everything (sub folders and files) from a folder except one file批处理命令从一个文件夹中删除除一个文件之外的所有内容(子文件夹和文件)
【发布时间】:2016-08-26 06:45:10
【问题描述】:

首先,过去已经回答了类似的问题,但不完全是我的问题。在其他一些解决方案中,建议隐藏文件夹/文件和更改属性,我不希望这样做,除非没有更简单的方法可用。另外,我已经尝试过这里建议的解决方案(以及其他几个):MS-DOS command to delete all files except one

但由于两个原因无法满足我的需要:

  1. 这也删除了文件,我不想。
  2. 这并没有删除子文件夹,而只是删除了文件。

所以,我有文件夹 c:/users/data,在那里,我有 5 个文件夹和 6 个文件,我想删除除 web.config 之外的所有文件,为此我运行批处理文件,如下所示:

@echo off
for %%j in (C:\Users\data\*) do if not %%j == Web.config del %%j
pause

但是当我运行批处理文件时,这会删除所有文件,包括web.config,并且不会删除任何子文件夹,如果我使用/d 开关,它只会删除文件夹而不是文件。如何同时删除文件和文件夹?

【问题讨论】:

  • 检查for %%j in (C:\Users\data) do echo %%j的输出并验证%%j是否真的是你想要的(我怀疑......)reference
  • @Stephan,这是一个错字,我已经编辑了目录错误的问题,但问题是,这个for %%j in (C:\Users\data\*) do echo %%j 只输出文件而不是所有内容,如果我说像for /d %%j in (C:\Users\data\*) do echo %%j 这样的话,那么只输出文件夹,而我想同时查看文件和文件夹..
  • 检查for %%j in (C:\Users\data\*) do echo %%j 的输出并重新考虑if not C:\Users\data\web.config == web.config 是否可以工作......
  • 将文件复制到别处有什么问题,删除所有内容并将文件放回原处?至少您的批处理文件将更具可读性,因此更易于维护。
  • @Dominique,只有一个问题,我想从其中删除除 web.config 之外的所有内容的 50 多个文件夹,然后从另一个文件夹中复制到这 50 个文件夹中,因此,我认为( mvho),另一个复制命令会增加一点时间问题。但是,请提出一些建议,我将非常乐意尝试..

标签: batch-file cmd


【解决方案1】:

我会这样做:

pushd "C:\Users\data" || exit /B 1
for /D %%D in ("*") do (
    rd /S /Q "%%~D"
)
for %%F in ("*") do (
    if /I not "%%~nxF"=="web.config" del "%%~F"
)
popd

基本代码取自我对问题Deleting Folder Contents but not the folder 的回答,但del 命令被第二个for 循环替换,该循环遍历所有文件并仅删除那些未命名为web.config 的文件。

请注意,这种方法不会触及原始父目录,也不会触及原始文件web.config。这一事实的最大优点是不会丢失任何属性(例如,创建日期和所有者)。

说明

  • 通过pushd切换到根目录;如果失败,请跳过脚本的其余部分;
  • 通过for /D 循环遍历根目录的所有直接子文件夹,并通过rd /S 递归删除它们及其所有内容;
  • 通过标准for循环遍历位于根目录中的文件;使用循环变量的~nx修饰符扩展每个文件的基本名称(n)和扩展名(x),以不区分大小写的方式将其与给定文件名(if)进行比较(@ 987654336@) 并通过del 删除文件,仅在不匹配的情况下 (not);
  • 最后通过popd恢复以前的工作目录;

您的代码中的主要问题是:

  • 您将比纯文件名与预定义名称进行更多比较,因此不会找到任何匹配项。
  • 您需要使用不区分大小写的比较,因为 Windows 不关心搜索文件名的大小写。
  • 您没有在比较表达式周围加上引号,因此您可能会收到语法错误消息,具体取决于文件名中出现的特殊字符。
  • 您正在使用del 命令仅删除文件;要删除目录,您还需要使用 rd

【讨论】:

  • 你能解释一下这个脚本是如何工作的吗,这对我很有帮助......
  • 在您有机会检查它们是否包含您不想删除的文件之前,您不是要删除所有文件夹及其内容吗?
  • @KlitosKyriacou,据我了解,要从删除中排除的文件位于根文件夹C:\Users\data,所以这是可行的;如果文件web.config 在其子文件夹之一中,那么您是对的,它将被删除;我希望我没有误解这个问题......
  • 我实现了一个简短的解释——见我的edit...
  • @aschipfl,web.config 文件将永远在这里c:\user\data\web.config
【解决方案2】:

我不确定 web.config 文件存储在哪里,或者是否有多个,所以...

只有一个web.config 文件

只需锁定文件(将文件重定向为输入)并删除其他任何内容

@echo off
    setlocal enableextensions disabledelayedexpansion

    pushd "c:\users\data" && >nul 2>nul (
        <"web.config" rmdir . /s /q
        popd
    )

代码将

  1. (pushd) 切换到目标文件夹(我们需要确保这只会从预期位置删除信息)将其设置为当前活动目录并锁定它(我们无法删除当前活动目录)。如果命令可以更改到文件夹,那么

  2. (rmdir) 将web.config 重定向为rmdir 命令的输入。这将锁定文件,因此在命令结束之前无法将其删除。 rmdir . /s /q 删除当前活动目录内(及以下)未锁定的任何内容

  3. (popd) 取消pushd命令恢复之前的活动目录

多个文件夹中的多个 web.config 文件

按照@Dominique 指出的approach(复制、清理、恢复)

@echo off
    setlocal enableextensions disabledelayedexpansion

    pushd "c:\users\data" && >nul 2>nul (
        for %%t in ("%temp%\%~n0_%random%%random%%random%.tmp") do (
            robocopy . "%%~ft" web.config /s
            robocopy "%%~ft" . /mir
            rmdir "%%~ft" /s /q
        ) 
        popd
    )

代码将

  1. (pushd) 更改为目标文件夹(我们需要确保这只会从预期位置删除信息)。如果命令可以更改到文件夹,那么

  2. (for) 准备对要使用的临时文件夹的引用(随机名称)

  3. (robocopy) 仅将web.config 文件(及其文件夹层次结构)从源文件夹复制到临时文件夹

  4. (robocopy) 将临时文件夹镜像到源文件夹。这将删除临时副本中未包含的所有文件/文件夹

  5. (rmdir) 删除临时文件夹

  6. (popd) 取消pushd命令恢复之前的活动目录

一旦web.config 文件被保存,由于源中的文件将与 temporay 文件夹中的文件匹配,它们不会被第二个robocopy 调用复制回来,但源中的任何文件/文件夹不是临时文件夹中的存在将被删除以镜像临时文件夹中的结构。

【讨论】:

    【解决方案3】:

    我也设法做到了,与@aschipfl 非常相似

    For /D %%k in (C:\Users\data) do (For /d %%m in ("%%k\*") do rmdir /s /q "%%m"
    For %%m in ("%%k\*") do if not %%m == %%k\Web.config del /q "%%m")
    

    【讨论】:

    • 嗯...对我来说,这个答案看起来不过是我的副本,但还有一个额外的无用 for /D %%k 循环和一些语法缺陷...
    • @aschipfl,这就是我说的原因,与您的非常相似..我没有将我的答案标记为答案,而是您的答案。在语法缺陷方面,正如我在第一个问题中提到的那样,我不是专家,而是在学习并且在经历不同的解决方案时,我将它们混合在一起,包括你的......
    • 最外层的for /D %%k 循环的目的是什么?你知道它只会迭代一次,在%%k 中返回C:\Users\data(即使目录不存在);我建议将if 查询更改为if /I not "%%m"=="%%k\Web.config"(引用避免了一些特殊字符的麻烦,/I 定义了不区分大小写的比较)...
    • @aschipfl,是的,我知道它只会迭代一次,我只需要选择C:\Users\data 中的所有内容,然后首先删除目录,然后删除除web.config 之外的所有文件。是的,你是对的,我肯定会将if 查询替换为if /I not "%%m"=="%%k\Web.config"。另一件事,在您提出的解决方案中,我是否没有您提到的问题 即使目录不存在,我的查询也会循环
    • for /D %%k in (C:\Users\data) do 不会返回C:\Users\data 的内容,它会迭代一次,只返回C:\Users\data 本身,甚至不访问文件系统(for 这样做只有 i> 如果提供了通配符*?);因此将代码中的每个%%k 替换为C:\Users\data 的行为完全相同。在我的解决方案中,|| exit /B 1 让脚本在pushd 失败的情况下终止,这意味着路径不存在...
    猜你喜欢
    • 1970-01-01
    • 2015-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-06
    • 1970-01-01
    • 2016-02-29
    • 1970-01-01
    相关资源
    最近更新 更多