【问题标题】:Batch Script that checks a directory for duplicate files检查目录中是否存在重复文件的批处理脚本
【发布时间】:2018-05-23 19:43:46
【问题描述】:

例如,试图浏览一个文件,

C:\Users\Admin\Desktop\Test\12345

C:\Users\Admin\Desktop\Test\45635

C:\Users\Admin\Desktop\Test\12345-2018-04-21

并创建一个名为“12345”的子文件夹,并将两个文件(12345 和 12345-2018-04-21)存储在子文件夹“12345”中。这将遍历整个文件夹以确保没有副本

:: ---------------------------------------------------------------
:: - This is a program that searches for files with the same 5 
::   digit number and puts them in a subfolder.
:: ---------------------------------------------------------------
@ECHO off

SETLOCAL
SET "sourcedir=C:\Users\Admin\Desktop\Test"
SET "destdir=C:\Users\Admin\Desktop\Test"
SET /a lastnum=200000

if "%first5%" equ "%lastnum%"(
SET "destdir=%destdir%\%first5%-sub"
 md %destdir%
)

FOR /f "delims=" %%a IN (
 'dir /b /a-d /on "%sourcedir%\*" '
 ) DO (
 CALL :detect "%%a"
 IF DEFINED dupnum (ECHO(MOVE "%sourcedir%\%%a" "%destdir%\")
)

GOTO end 

:: Routine to detect whether the first 5 characters of the filename "%1"
:: are all numeric and if so, whether they match the previous 5-digit number
:: found.

:detect
SET "dupnum="
:: Get the first 5 characters of the filename; prefix with a `1`
SET "fullfilename=%~1"
SET "first5=1%fullfilename:~0,5%"
IF "%first5%" neq "%lastnum%" (
 SET "lastnum=%first5%"
   GOTO end
)
:: First 5 chars of this filename = first 5 of previous filename
:: Check to see whether numeric
SET /a dummy=first5 + 0
IF "%dummy%" neq "%first5%" (
 SET "lastnum=%first5%"
   GOTO end 
)
SET "dupnum=Y"
   GOTO end 

ENDLOCAL

:end

PAUSE

不知道为什么我不能让它创建一个文件夹并将重复的文件存储到其中。它将通读我的测试文件夹并注意到重复项并提示移动它们,但我不确定将其移动到新文件夹需要做什么。

【问题讨论】:

  • 嗯,你不能在同一个文件夹中有两次相同的文件名,所以我不明白你所说的重复文件是什么意思。
  • 让我澄清一下,对不起。他们扫描的文件将它们的 pdf 文件放入其服务器上的文件夹中。如果有副本,它将在名称末尾添加日期。所以我需要检查前5位数字是否相同。
  • 律师事务所根据随机获取的信息为每个文件命名,该信息将获得一个 5 位数字。

标签: file batch-file duplicates directory


【解决方案1】:

如果您以前没有接触过该语言,则很难确定从哪里开始。

第一个问题是正确指定您的术语的含义。例如,“重复文件”通常意味着重复的 contents 或重复的 name(但由于一个目录只能保存一个具有任何特定名称的文件,这意味着不同的目录)。在您的情况下,您的 individual 定义是“名称以相同 5 位数字开头的文件”。

由于这会导致批次使用多种技术(并且可能有多种方法),因此可以使用以下方法:

@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET /a lastnum=200000

md %destdir% 2>nul

FOR /f "delims=" %%a IN (
 'dir /b /a-d /on "%sourcedir%\*" '
 ) DO (
 CALL :detect "%%a"
 IF DEFINED dupnum (ECHO(MOVE "%sourcedir%\%%a" "%destdir%\")
)

GOTO :EOF

:: Routine to detect whether the first 5 characters of the filename "%1"
:: are all numeric and if so, whether they match the previous 5-digit number
:: found.

:detect
SET "dupnum="
:: Get the first 5 characters of the filename; prefix with a `1`
SET "fullfilename=%~1"
SET "first5=1%fullfilename:~0,5%"
IF "%first5%" neq "%lastnum%" (
 SET "lastnum=%first5%"
 GOTO :eof
)
:: First 5 chars of this filename = first 5 of previous filename
:: Check to see whether numeric
SET /a dummy=first5 + 0
IF "%dummy%" neq "%first5%" (
 SET "lastnum=%first5%"
 GOTO :eof
)
SET "dupnum=Y"
GOTO :eof

您需要更改sourcedirdestdir 的设置以适应您的情况。

所需的 MOVE 命令仅用于测试目的ECHOed。 验证命令正确后,将ECHO(MOVE 更改为MOVE 以实际移动文件。附加>nul 以禁止报告消息(例如1 file moved

从根本上说,批处理代码不区分大小写,for 语句中的 metavariable 明显例外(上面的%%a

但是,Batch 对布局非常敏感,因此最好进行剪切和粘贴,而不是重新键入并尝试重新格式化以适应一些更赏心悦目的风格。

通常假定批处理代码是在提示符下运行的,而不是通过“单击”来运行的。

语法SET "var=value"(其中值可能为空)用于确保分配的值中不包含任何杂散的尾随空格。 set /a 通常可以“无引号”使用。

@echo off 语句关闭命令回显,以便命令在执行前回显到控制台。

setlocal 语句调用“本地环境”,以便在批处理完成时处理对环境的任何更改或添加。

主循环首先执行dir 命令以生成目录列表。选择的选项是 /b - 基本(无页眉/页脚 - 仅名称)/a-d - 无目录名称和 /on - 按名称排序(即按字母顺序)

dir 命令的输出随后由带有"delims=" 选项的for /f 处理。这会将 整个 行分配给 metavariable %%a

对于找到的每个文件名,都会执行子程序:detect。由于该程序位于此批处理文件中,因此在 call 语句中使用了 :。如果没有:,例程called 将是一个名为detect 的批处理文件(detect.batdetect.cmd,前者更受欢迎)

在执行例程:detect 后,可能会或可能不会设置名为dupnum 的变量。如果已设置,则为 echo 字符串。如果没有,不要。

例程:detect 首先将dupnum(例程的结果)“设置”为一个空字符串,如果变量存在,它将从环境中删除。

然后将变量fullfilename 设置为从call 语句传递的值。 %1 表示“第一个参数”。 %~1 表示“并删除引号”。需要引号以允许传递的文件名包含空格。

然后我们从完整文件名中获取前 5 个字符(从“字符 0”中获取 5 个字符)并在其前面加上 1。如果在数学运算中使用,Batch 将以 0 开头的字符串视为 八进制 字符串,因此 1 前缀确保现在的 6 个字符被解释为十进制。

现在 - 如果first5 不等于lastnum,那么我们记录新的lastnumgoto :eof 退出子程序。 dupnum 没有设置,所以调用循环不会显示这个文件名。

接下来,我们只想在前 5 个(好吧,现在是 6 个)字符都是数字的情况下进行移动。我们可以使用set /a 以数学模式将0 添加到字符串中,这将产生相同的数字(如果这些字符都是数字)或不同的数字(直到第一个非数字),如果“first5”包含一个非数字。

所以 - 测试结果 - 如果不同,“first5”包含一个非数字,所以在 dupnum 未设置的情况下退出。如果相同,则设置dupnum,以便报告文件名。

还请注意,官方备注说明是rem,但::(这是一个损坏的标签 - 无法到达的标签)通常用于代替备注,因为它打字更容易,对眼睛的干扰也更少。但请注意,:: 样式不能在 code-blocks 中使用(括号内的语句分组)


我添加了一个新行,md ...,它应该创建目标目录。如果该目录已经存在,2>nul 会抑制错误消息。如果您希望此目录成为源目录的子目录,则设置 destdir 如下:

set "destdir=%sourcedir%\subdirectorynamedesired"

【讨论】:

  • 欣赏它,伙计。有很大帮助。你认为我可以通过制作一个 C++ 程序来完成同样的任务吗?这对我来说更容易理解和编码。
  • 我已经稍微调整了你的代码,但我无法让它创建一个子文件夹并通过文件进入它。它会回显它正在移动文件但不创建子文件夹。
猜你喜欢
  • 1970-01-01
  • 2018-12-08
  • 2011-01-01
  • 2015-07-09
  • 1970-01-01
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 2013-04-11
相关资源
最近更新 更多