07 Windows批处理之文件操作

如果你问一个对批处理不太熟悉的程序员它的主要用途,他们的回答可能会提到移动文件。批处理可以做更多的事情,但毫无疑问,它的主要用途之一是文件移动。在本文中,我们将探索不同的命令和可用的技术。您还将了解如何创建空文件,以及合并、移动、重命名和删除文件的方法。我将介绍文件掩码和通配符,允许您在许多类似命名的文件上执行命令,而不仅仅是一个。

文件复制命令

批处理有三个用于复制文件的命令:copyxcopyrobocopy。在本节中,我将对它们进行比较,并就何时使用它们给出建议,因为它们都有各自的应用场景。您正在复制许多小文件还是几个大文件?网络稳定吗?速度是一个考虑因素吗?您想要一个直接的返回代码还是一个更微妙的返回代码?日志对你有多重要?在为任何特定副本决定最佳命令和选项之前,您需要回答许多问题。

copy

copy命令提供了一种快速简便的方法来创建空文件:

copy nul D:\Batch\EmptyFile.dat

在批处理中,单词null表示永远为空或为空的文件。这里,我们复制null文件来生成一个空文件,文件的路径和名称由我们选择。一个有趣的事实:Windows不允许您在任何文件夹中创建名为nul的文件,即使是手动创建也不行。快去试试吧。

我使用copy命令的唯一其他用途是合并两个或多个相对较小的文件。/B选项执行二进制文件复制,这意味着每个字节,甚至是特殊字符,如回车和换行,都被不加更改地复制,从而导致文件的真正连接。源文件以加号分隔,后面跟着合并后的文件:

copy /B D:\Batch\07\Header.txt + D:\Batch\07\Details.txt D:\Batch\07\MergedFile.txt

我们在这里连接两个文件,但是我们可以用更多的加号分隔符合并更多的文件。

您可能已经注意到,我只提到了copy命令的两种用法,这两种用法都不涉及复制实际文件。您可以使用该命令来复制文件,但我从不将其用于此目的,因为它很原始,而且选项很少。这些缺点在批处理的第一个版本发布后不久就显现出来了,它很快就被更有用和可配置的xcopy命令所取代。

xcopy

xcopy命令的基本语法有两个参数——源文件和目标路径:

xcopy D:\Batch\07\Source\FileCopy.txt D:\Batch\07\Target\

xcopy命令的一个巨大优点是,如果目标目录还不存在,它将创建目标目录。相反,copy命令找不到路径,会提示复制失败。

在前面的示例中,只给出了目标路径,这意味着复制的文件将具有与源文件相同的名称。但是我们可以将目标文件重命名为xcopy命令的一部分,只需给它一个文件名:

xcopy D:\Batch\07\Source\FileCopy.txt D:\Batch\07\Target\RenameFileCopy.txt

这个命令有时会失败,因为解释器不确定目标是一个目录还是一个文件(在后面的文章中,我们再一起来讨论如何让该命令一直有效)。

xcopy命令有两个选项,我几乎每次调用该命令时都会使用这两个选项。/Y选项抑制确认覆盖目标文件的提示。虽然在通过命令提示符或交互方式运行时请求确认可能是有意义的,但在大多数其他情况下,它只会停止处理并创建挂起,因此最好将其关闭。(强制覆盖)。

另一个我不能没有的选项是/F。它显示复制的每个文件的完整源路径和目标路径以及文件名,当使用通配符复制多个文件时,这会留下有用的审计跟踪。如果没有/F选项,则只显示源文件或多个文件以及总文件数。在另一种极端情况下,如果你对所有这些信息不感兴趣,你可以使用/Q选项(静音模式)来关闭显示器。

使用这两个不可或缺的选项,下面的命令将取消提示并提供详细的日志记录:

xcopy D:\Batch\07\Source\FileCopy.txt D:\Batch\07\Target\ /Y /F

这个命令有太多可用的选项;使用help命令获取完整列表。然而,作为一个小的案例,/U选项只复制目标中已经存在的文件;/S选项复制文件夹和子文件夹;/J选项使用无缓冲的I/O,这对于非常大的文件是最优的。

D:\Batch\07>xcopy /?
复制文件和目录树。

XCOPY source [destination] [/A | /M] [/D[:date]] [/P] [/S [/E]] [/V] [/W]
                          [/C] [/I] [/-I] [/Q] [/F] [/L] [/G] [/H] [/R] [/T]
                          [/U] [/K] [/N] [/O] [/X] [/Y] [/-Y] [/Z] [/B] [/J]
                          [/EXCLUDE:file1[+file2][+file3]...] [/COMPRESS]

 source       指定要复制的文件。
 destination  指定新文件的位置和/或名称。
 /A           仅复制具有存档属性集的文件,
              不会更改属性。
 /M           仅复制具有存档属性集的文件,
              关闭存档属性。
 /D:m-d-y     复制指定日期或之后更改的文件。
              如果未提供日期,仅复制其源时间
              比目标时间晚的文件。
 /EXCLUDE:file1[+file2][+file3]...
              指定包含字符串的文件列表。每个字符串
              应在文件中单独一行中显示。当有任何
              字符串与要复制的文件的绝对路径的任何部分
              匹配时,将从复制中排除该文件。
              如果指定 \obj\ 或 .obj 之类的字符串,将分别
              排除 obj 目录下的所有文件或具有 .obj 扩展名的
              所有文件。
 /P           在创建每个目标文件之前提示你。
 /S           复制目录和子目录(空目录除外)。
 /E           复制目录和子目录(包括空目录)。
              与 /S /E 相同。可用于修改 /T。
 /V           验证每个新文件的大小。
 /W           提示你在复制前按一个键。
 /C           即使发生错误,也继续复制。
 /I           如果目标不存在并复制多个文件,
              则假定目标必须是目录。
 /-I          如果目标不存在并复制单个指定文件,
              则假定目标必须是文件。
 /Q           在复制时不显示文件名。
 /F           在复制时显示完整的源文件名和目标文件名。
 /L           显示要复制的文件。
 /G           允许将加密文件复制到
              不支持加密的目标。
 /H           还复制隐藏文件和系统文件。
 /R           覆盖只读文件。
 /T           创建目录结构,但不复制文件。不
              包括空目录或子目录。/T /E 包含
              空目录和子目录。
 /U           仅复制目标中已存在的文件。
 /K           复制属性。普通 Xcopy 将重置只读属性。
 /N           使用生成的短名称复制。
 /O           复制文件所有权和 ACL 信息。
 /X           复制文件审核设置(隐含 /O)。
 /Y           禁止提示确认是否要覆盖
              现有目标文件。
 /-Y          发出提示,要求确认是否要覆盖
              现有目标文件。
 /Z           在可重启模式下复制联网文件。
 /B           复制符号链接本身与链接的目标。
 /J           使用未缓冲的 I/O 进行复制。建议用于非常大的文件。
 /COMPRESS    在文件传输期间请求网络压缩
              (如适用)。
 /SPARSE      复制稀疏文件时保留稀疏状态。

可在 COPYCMD 环境变量中预设开关 /Y。
可在命令行上使用 /-Y 重写该项。

虽然copy已经被xcopy取代了,但是从技术上讲,微软认为xcopy本身已经被替换为更新的robocopy命令。即便如此,xcopy命令的广泛使用意味着它仍然可以在可预见的操作系统中使用,我将很快详细说明,在许多情况下,它仍然是更好的选择。

robocopy

robocopy实际上代表的是robust copy,这不是夸张。虽然xcopy有许多有用的选项,但robocopy提供了一些令人印象深刻的日志记录和一系列令人难以置信的选项。

尽管robocopy命令比xcopy强大得多,但它也很容易使用。参数有点不同:首先提供不带文件名的源目录,然后是目标目录,最后是要复制的一个或几个文件或文件掩码:

robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ FileCopy.txt

这个例子在功能上等同于上一节中的xcopy命令,并复制在这里:

xcopy D:\Batch\07\Source\FileCopy.txt D:\Batch\07\Target\

因为robocopy命令的前两个参数已知是路径,所以可以省略末尾的斜杠,这比xcopy有很大的优势,在xcopy中,若将最后的斜杠遗漏的化,将导致目标目录转换为文件名。

robocopy 日志

要了解robocopy到底有多强大,只需看看它的日志记录功能即可。如果你是一名xcopy的爱好者,请先坐好再看前面。冗长是我脑海中浮现的唯一一个词,即便是这个词也不够。除了复制的文件列表之外,日志还包括一个花哨的头、开始和结束时间、文件大小、复制速度统计、源和目标路径、复制和跳过的文件和目录的总数、以及任何失败的复制、使用的命令行选项列表,等等。为了提高可读性,它甚至还使用了大量的空白进行了很好的格式化。

前面展示的简单robocopy命令复制单个文件会生成以下日志:

D:\Batch\07>robocopy Source\ Target\ FileCopy.txt

-------------------------------------------------------------------------------
   ROBOCOPY     ::     Windows 的可靠文件复制
-------------------------------------------------------------------------------

  开始时间: 2024年9月9日 07:04:42
        源: D:\Batch\07\Source\
      目标: D:\Batch\07\Target\

      文件: FileCopy.txt

      选项: /DCOPY:DA /COPY:DAT /R:1000000 /W:30

------------------------------------------------------------------------------

                           1    D:\Batch\07\Source\
            新文件                     0        FileCopy.txt

------------------------------------------------------------------------------

                  总数        复制        跳过       不匹配        失败        其他
       目录:         1         0         1         0         0         0
       文件:         1         1         0         0         0         0
       字节:         0         0         0         0         0         0
       时间:   0:00:00   0:00:00                       0:00:00   0:00:00
   已结束: 2024年9月9日 07:04:42

有些结果是不言自明的,如Total、replicated和FAILED,但其他结果则不然。如果要复制的文件已经在目标路径中并且是相同的,robocopy足够聪明,不会浪费时间覆盖它,而是认为它可以合理地跳过。当由于源文件和目标文件夹(或源文件夹和目标文件)具有相同的名称而阻止复制时,就会发生不匹配。附加文件是不在源但已经在目标的文件和目录。显然,这些文件没有被复制,但解释器觉得有义务注意到它们的存在。对于这种复制一个小文件的任务,日志记录可能是多余的。更有趣的任务可能会继续执行页面,但是对于更有趣的任务,日志记录可能是无价的。

默认情况下,所有这些信息都被写入控制台(在后续的文章中,我将讨论如何将日志记录从任何命令甚至整个bat文件重定向到日志文件)。但是robocopy命令的独特之处在于,您可以使用选项轻松创建日志文件。日志文件的路径和名称只跟随适当命名的/LOG选项,用冒号分隔。

这可能是您第一次看到一个选项在斜杠后面有多个字符,而这个命令有更多的字符。向选项/LOG+添加加号会导致信息被附加到日志文件中,如果它已经存在的话。为了证明这一点,请考虑以下几点:

set roboLog=D:\Batch\07\Robocopy.log
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ FileCopy.txt /LOG:%roboLog% /NP
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ AnotherFileCopy.txt /LOG+:%roboLog% /NP

在将roboLog定义为日志文件的路径和名称之后,将在两个robocopy命令中使用它。第一个命令使用其复制中的信息创建日志文件,如果存在的话覆盖现有文件,第二个robocopy命令将其复制的结果追加到该日志文件中。

最后两个命令都使用/NP选项,它代表无进度,因为我认为在创建日志文件时必须使用它。如果将信息写入控制台,则每个复制的进度以百分比形式实时显示,每秒更新多次。在最终显示100%之前,相对较大的文件可能会显示几十个值。在控制台中查看时,这种状态非常好,但在日志文件中,每次更新都会变成一条新记录。不需要很多大文件就可以把日志变成一团乱麻。即使是小文件也可能导致日志文件中出现一些额外的不需要的记录。/NP选项很好地解决了这个问题,只在每次复制完成后更新日志。

有用的robocopy选项

robocopy有许多复制选项,所以我将快速地介绍最有用的选项。但首先,这里有一个命令作为选项的基础:

robocopy D:\Batch\07\Source\ D:\Batch\07\Target\

这个简单的命令(缺少文件的第三个参数)将源目录中的所有文件复制到目标目录。

该命令自动执行失败副本的重试,这非常棒,但是默认的重试次数是惊人的100万次,每次尝试间隔30秒等待。这可能会导致一个有致命缺陷的复制延迟几个月。/R/W选项分别覆盖默认的重试次数和以秒为单位的等待时间:

robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /R:20 /W:5

使用这些选项,解释器将重试失败的副本多达20次,每次尝试之间间隔5秒,然后启动中止。选择对您和您的设备有意义的值,但不能保留默认值。

如果你添加/S选项,它也会复制所有的子目录,除了空的子目录:

robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /S

/E选项复制所有的子目录,空的和非空的都一样:

robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /E

您可以细化此选项,只复制源目录(D:\Batch\07\Source\)及其直接子目录中的文件,而不复制更低级别的子目录。/LEV选项定义了级别的数量,包括根节点,为2以处理:

robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /E /LEV:2

对于非常大的文件,无缓冲的I/O更有效,并且使用/J选项调用非常奇怪。(这个选项是从xcopy命令借来的,在xcopy命令中已经使用了/U选项。)/MIN/MAX选项设置要复制的文件的最小和最大字节限制。以下两个命令复制文件夹中的所有文件,仅对至少1GB的文件使用无缓冲I/O:

robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /MIN:1000000000 /J
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /MAX:999999999 /MT

我将/MT选项(它代表多线程)隐藏到用于较小文件的命令中。默认情况下,robocopy命令按顺序复制文件,但该选项并行复制8个文件。你甚至可以定义线程的数量;/MT:128是最大值,但根据我的经验,这并不比选项默认值8快多少。我们可以讨论阈值,但是对于大文件的无缓冲I/O和对于小文件的多线程将优化任何复制。

/MINAGE/MAXAGE选项定义要根据最后修改日期复制的内容。您可以单独或一起使用它们来创建日期范围。以下命令只复制自2000年9月14日微软灾难性地发布Windows Me以来触及的文件,不包括过去7天内更改的任何文件:

robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /MAXAGE:20000914 /MINAGE:7

您可以将这两个选项的值定义为日期(格式为CCYYMMDD)或天数。解释器足够聪明,知道这个8字节的数字表示的是一个日期,而不是超过5万年的时间跨度。任何少于1900的数字都被解释器认为是天数。

/PURGE选项删除目标中的额外文件和目录,显然您应该谨慎使用,但它是创建备份的一个非常方便的工具。如果有一天你备份了一个文件夹,第二天改变了源目录中的文件名称,然后再次备份该文件夹,那么你最终会在备份中得到一个无关的文件,除非你使用了/PURGE选项。更好的是/MIR选项,它的镜像一个目录树。/MIR选项基本上完成了/PURGE选项的功能,但它包含子目录。

/XF选项从副本中排除一个或多个文件,而/XD类似地排除一个或多个目录。/L选项不复制任何东西;它会生成一个列表,其中包含了如果没有使用该选项将被复制的所有内容。

您也可以使用robocopy命令来移动文件。与之前一样,使用help命令获取可用选项的完整列表。

robocopy返回码

xcopy命令与大多数批处理命令类似,成功执行将返回错误级别0,而失败执行将返回非0的数字。相比之下,robocopy是独一无二的——如果不理解这种独特性,就会产生很多困惑。返回代码为0表示没有复制任何内容,但如果至少复制了一个文件,解释器将返回1到15(包括1到15)之间的奇数,但即使其中一些代码也不完全是好的返回代码。下面是robocopy命令生成的六个基本返回代码:

  • 0 ---> 没有错误,但没有文件被复制;换句话说,所有文件都被跳过了。
  • 1 ---> 成功复制一个或多个文件。
  • 2 ---> 发现了一个或多个额外的文件或目录;没有复制。
  • 4 ---> 发现一个或多个不匹配;没有复制。
  • 8 ---> 无法复制某些文件或目录。
  • 16 ---> 没有任何东西被复制;有一个严重的错误。

使用代码0到5不是更简单吗?不,中间的四个代码并不是相互排斥的;也就是说,有可能不止一个(甚至四个)同时为真。解释器将所有为真的代码相加,并将总和作为错误级别返回。

例如,设想一个将源文件夹中的所有文件复制到目标文件夹的robocopy命令,其中一些文件被成功复制,但目标文件夹也有额外的副本。返回码1和2都为真;因此,它们的和3作为错误级别返回。也有可能在复制文件时,发现了不匹配的额外内容,并且另一个文件由于被某人或某些进程打开而无法复制。计算一下(1 + 2 + 4 + 8),解释器返回15。

这些返回代码为精明的编码人员提供了微调错误处理的机会。返回代码1和3显然是好的,我通常认为3或更少也很好。从4到7的任何值都涉及不匹配,而高于4的任何值至少有一个显式故障。根据具体情况,不匹配可能是完全可以接受的,因此只有返回代码大于等于8才会被认为是错误的。

要显式地验证至少复制了一个文件,我们只需要查找奇数的返回代码,我们可以通过后面介绍的的modulo函数来实现。

xcopy vs. robocopy

尽管这个词带有主观色彩,但大多数批处理程序员都认为robocopy比xcopy好,因为它有无数的选项、多线程、自动重试、令人印象深刻的日志记录,以及使其更高效的幕后功能。但有一种主要的bat。当尝试复制单个文件时,xcopy错误处理到目前为止要好得多。这两个命令都试图复制一个不存在的命名文件:

xcopy D:\Batch\07\Source\NonExistentFile.txt D:\Batch\07\Target\
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ NonExistentFile.txt

xcopy命令报告没有复制任何文件,并返回errorlevel 4,但是robocopy命令返回0,表示没有错误,也没有复制任何文件。我认为这应该是一个错误。当尝试复制多个文件时,当没有源文件时,这两个命令都返回0——这是有意义的,但是这两个命令都调用要复制的显式文件,并且robocopy返回代码不区分未找到文件和被跳过的文件,因为它已经存在于目标目录中。跳过未更新的文件是robocopy的一个重要功能,但这与找不到文件是完全不同的。健壮的日志使这一点变得清晰,但返回码却没有。

返回码无法报告文件未复制(未找到或跳过)的原因,这是一个缺陷,但我们可以克服它。当使用robocopy命令复制一个特定文件时,可以在errorlevel为0时对目标文件执行if exist。如果存在,则正确跳过该文件;如果没有,则存在错误。或者,像我一样,在这种情况下使用xcopy。

在其他情况下,robocopy命令的复杂返回码超出了需要的范围。您可能不关心是否有额外的或不匹配的文件,而只想要一个简单的好或坏、零或非零的结果。这并没有什么错,说实话,出于习惯和易用性,我有时仍然会在新代码中使用它。

也就是说,正如它的名字所暗示的那样,robocopy命令要健壮得多。它更具可配置性、速度更快,而且更不容易出错。如果复制非常大的文件、大量的文件,或者由于连接问题而可能失败的文件,robocopy是合理的选择,而且复杂的返回码有时有一个很大的好处。此外,xcopy命令对路径和文件名的长度有254字节的限制。我从来没有接近超过这个限制,但如果你有,robocopy可以处理它。

关于这个主题,我要做的最明确的声明是,您永远不应该使用copy命令来复制文件,而是将其保留在工具箱中,以便创建空文件或合并文件。

文件模板和通配符

前面的所有xcopy示例都复制单个文件,而robocopy示例要么复制单个文件,要么复制目录中的所有文件。但是使用文件模板和通配符,你可以创建更有针对性的命令,只复制目录中的一些文件;实际上,它们可能在每次执行时复制不同数量的文件。文件模板替换这两个命令中的文件名,并由一个或多个通配符组成,可能包含一些硬编码文本或解析变量。然后,当它执行时,该命令复制所有满足或适合该文件掩码的文件。

文件模板并不是复制文件的命令所独有的。本文中即将介绍的移动、删除甚至重命名文件的命令也接受文件模板来代替文件名,允许你一次移动、删除和重命名多个文件。for命令充分利用了文件模板,我将在后续中演示如何使用。在文件上执行某些操作的任何命令都可能使用通配符;如果有疑问,可以尝试一下。

批处理将两个字符识别为通配符,星号(*)和问号(?)。它们的行为完全不同,我将使用xcopy命令详细说明它们,但首先让我们看一下要复制的一组文件。一个非常有条理的人可能会维护包含预算信息的电子表格,一年中每个月一个文件。在本演示中,D:\Batch\07\Budget\文件夹包含电子表格,其命名约定注明年份和月份。这里有三个例子:

Budget.January2008.xlsx
Budget.February2008.xlsx
Budget.March2008.xlsx

这些文件来自金融危机和大衰退开始的那一年,文件夹中包含了前后一年类似命名的文件,以及其他类型的文件。

星号通配符

星号是最常见的批处理通配符字符,是零到多个字符的替代品。为了演示,下面的xcopy命令复制2008年以来的所有文件,或者更具体地说,是D:\Batch\07\Budget\中满足Budget.*2008.xlsx模板的文件:

xcopy D:\Batch\07\Budget\Budget.*2008.xlsx D:\Batch\07\Target\ /F /Y

星号是通配符,表示该命令复制名称以Budget开头的每个文件。以2008.xlsx结尾,中间有一些东西,甚至什么都没有。如果一个名为Budget.2008.xlsx的文件恰好在文件夹中,它也满足模板,并且是复制的文件之一。

到年底,应该有12个这样的文件满足这个模板,每个月一个,导致命令复制所有12个文件。但该命令不会复制2007年或2009年的文件,也不会复制具有相同名称但扩展名不同的Word文档,例如Budget.June2008.docx。如果要从其中一个文件BudgetAugust2008.xlsx的名称中删除第一个点,解释器也不会复制它,因为它不满足模板。

在通配符之前插入字母J的下面非常微妙的变化导致命令只复制三个文件,分别是一月、六月和七月的文件:

xcopy D:\Batch\07\Budget\Budget.J*2008.xlsx D:\Batch\07\Target\ /F /Y

在通配符前再添加一个字符,Budget.Ju*2008.xlsx模板将排除一月份的文件。

您不限于模板中的单个通配符。以下是一个使用两个星号的示例,其中最后一个是扩展名的替换:

xcopy D:\Batch\07\Budget\Budget.*2008.* D:\Batch\07\Target\ /F /Y

前面提到的Word文档Budget.June2008.docx现在也被命中了。

现在您知道了星号通配符可以表示任何长度的任何文本,包括根本没有文本,但是有时您可能需要更严格的限制。批处理有一个鲜为人知的通配符,用于此目的。

问号通配符

虽然星号是零到多个字符的通配符,但问号通常是一个字符的通配符。为了只复制带有四个字符的月份的文件,我将在原来是星号的地方使用四个问号:

xcopy D:\Batch\07\Budget\Budget.????2008.xlsx D:\Batch\07\Target\ /F /Y

该命令复制6月和7月的文件,但不复制3月、4月、5月和所有其他月份的文件,因为这些月份比较冗长。

这看起来很简单,如果一组或多个问号通配符出现在文件模板的末尾,或者这些问号紧接在一个点之前,批处理还会将空值视为每个问号的有效替换值。

为了说明这一点,我将通过在月份和年份之间插入一个句号来调整文件命名约定,从而产生如下的文件名:

Budget.April.2008.xlsx
Budget.May.2008.xlsx
Budget.June.2008.xlsx
Budget.July.2008.xlsx

接下来,我将在文件模板的四个问号和年份之间插入点,如下所示:

xcopy D:\Batch\07\Budget\Budget.????.2008.xlsx D:\Batch\07\Target\ /F /Y

甚至一些有经验的批处理程序员也可能期望6月和7月的文件只满足这个掩码。它们是正确的,因为3月、4月和其他所有用四个以上字母表示的月份的文件将不会被复制,但5月的文件也将满足掩码。前三个通配符匹配May中的三个字母,但第四个问号匹配一个空字符或不存在的字符。即使是名字奇怪的Budget. 2008.xlsx也满足这个模板。

结果是,当n个问号通配符出现在文件模板的末尾或后面跟一个点时,模板将满足0到n个字符。否则,n个问号通配符恰好满足n个字符。这是一个非常微妙的奇怪现象,理解它可能会节省你几个小时的烦恼。

要注意两个批处理通配符之间的区别,shot、shoot、shut、shunt、shallot甚至sht都满足sh*t文件掩码。在这些词中,只有shot和shut能满足文件模板sh?t

短文件名和文件模板

作为一个更微妙的问题,有时看起来不满足文件模板的文件名最终满足了模板。我们所认为的文件名实际上是一个很长的文件名。默认情况下,Windows还会为计算机上的每个文件分配一个简短的文件名。这是旧操作系统中很少使用的遗留,但它仍然存在,当解释器将文件与模板进行比较时,它会根据长文件名或短文件名查找匹配。

短文件名最多八个字节长,扩展名不超过三个字节。若恰好命名为NineBytes.Long的文件名,可能有一个短的文件名如NINEBY~1.LON。如果尝试复制扩展名不超过三个字节的所有文件,使用*.???文件模板,解释器复制具有四字节扩展名的文件,因为它的短文件名满足掩码。这个问题不经常出现,但是如果你在一个文件上得到了意外的命中,检查它的短文件名。

文件移动

移动文件类似于复制文件;唯一的区别是,文件被复制后,它存在于两个地方,而文件被移动后,原始文件不再存在。move命令可以轻松地执行此任务。它只是将源和目标作为参数,你通常会看到它带有/Y选项,以抑制覆盖目标的确认提示:(强制移动)

move D:\Batch\07\Source\FileMove.txt D:\Batch\07\Target\ /Y

许多旧代码仍然包含move命令,但它在很大程度上已被弃用,取而代之的是robocopy命令。以下带有/MOV选项的命令在功能上等同于前面的move命令:

robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ FileMove.txt /MOV

从robocopy命令中移动文件名会移动源文件夹中的所有文件,但不会移动子文件夹中的任何文件。

添加/S选项会移动所有子文件夹中的所有内容,即使需要创建目标子文件夹:

robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /MOV /S

该命令移动所有文件。它们不再位于源文件夹,但源文件夹结构仍然保留。这是它有点奇怪的地方。我们一直在讨论/MOV选项,它显然是move的缩写,但一个类似的命名选项/MOVE代表……这两个选项有微妙的不同。带有/MOVE选项的robocopy命令真正地移动文件和目录。

将E添加到选项后,将在将所有文件复制到目标后删除源目录结构:

robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /MOVE /S

我们有一个/MOV选项,它在复制子目录时移动文件,还有一个/MOVE选项,它同时移动文件和子目录。它不是特别直观。

当考虑到使用哪个命令进行特定的移动时,robocopy命令在前面的“xcopy vs robocopy”中提到的所有相同原因的最有效的选择。但就像xcopy命令一样,移动命令具有更直接的返回代码,而且在批处理生态系统中仍然有一个位置。

文件删除

当文件不再需要时,清理它们是有意义的。del命令很容易删除一个或多个文件。/Q选项,再次代表安静模式,防止解释器请求删除文件的权限。该命令接受要删除的文件的多个参数,其中可以使用显式文件名和文件模板。下面的命令删除一个名为Junk.txt的特定文件和扩展名为.OLD的文件夹中的所有文件:

del /Q D:\Batch\07\Source\Junk.txt D:\Batch\07\Source\*.OLD

使用/A选项根据文件的属性选择要删除的文件。例如,使用/AH选项只删除隐藏文件。相反,/A-H选项只删除未隐藏的文件。与往常一样,使用help命令获取完整的选项列表。

通过简单地使用目录作为del命令的参数来删除文件夹中的所有文件,但是目录本身仍然存在。

文件重命名

renrename命令是批处理同义词;也就是说,它们是同一个命令。第一个参数是要重命名的文件,第二个参数是新的文件名:

ren D:\Batch\07\FileRename.txt NewFileName.txt

如果目标文件已经存在,解释器返回错误级别1。如果有相同名称的文件可能已经存在,我会在重命名之前悄悄地删除它:

del D:\Batch\07\NewFileName.txt /Q
ren D:\Batch\07\FileRename.txt NewFileName.txt

即使对于这个命令也支持通配符,但是我只将ren命令用于显式文件名,主要是因为该命令不会将重命名的文件列表写入控制台。

ren命令并不复杂,在两个参数上都使用路径是很容易的,但是当您仔细考虑这个问题时,解释器已经知道了第一个参数的路径。文件没有被移动或复制到任何地方;根据该命令的性质,它被就地重命名。如果第一个参数没有路径,则假定当前目录,但第二个参数仅为新文件名,并且不应该与之关联路径。

总结

如果没有创建、复制、移动、合并和删除文件的能力,批处理就什么都不是,我在这里介绍了一组用于这些任务的命令。我讨论的一些命令很简单,但是我讨论了不止一个问题以及减轻这些问题的解决方案。您还学习了如何使用文件模板和通配符一次在多个文件上执行这些命令。

复制文件听起来似乎是一项简单的任务,但我详细介绍了许多可用的技术和注意事项。我希望我向您展示了robocopy命令的强大和有用性,同时也向您灌输了xcopy命令的简单性和实用性。

在下一篇文章中,我将描述如何执行用另一种语言编译的程序,这将涉及到更深层次的讨论,即当您没有提供路径时,解释器如何找到要执行的程序。

本文由博客一文多发平台 OpenWrite 发布!