简体   繁体   English

用于复制特定文件的批处理文件变量

[英]Batch File Variable to copy specific files

I'm trying to copy specific files from C: to " X: for example".我正在尝试将特定文件从C:复制到“例如X: ”。 The files are named with the same format.这些文件以相同的格式命名。

A1234_ZZabc123_DT1_F1.tst 
A4567_ZZdef4567_DT2_F2.tst 
A8901_ZZghi1289_DT1.tst 
A2345_ZZjfkbu12_to_modify.tst 
A6789_ZZlmny568_F1_to_modify.tst 
A1234_ZZabc478_DT1.txt 

I want to copy only the .tst files, and with the same format as the first 3 Axxxx_ZZyyyxxx_DTx_Fx.tst where x =number and y =letter.我只想复制.tst文件,格式与前 3 个Axxxx_ZZyyyxxx_DTx_Fx.tst相同,其中x = 数字, y = 字母。

After ZZ, it might be 4 letters and 3 numbers, or 5 letters and 4 numbers, like a "namecode".在 ZZ 之后,它可能是 4 个字母和 3 个数字,或者 5 个字母和 4 个数字,就像一个“namecode”。 Example: ZZkusha122 or ZZkus1551 .示例: ZZkusha122ZZkus1551 I need to copy the folders along with the files too.我也需要将文件夹与文件一起复制。

I'm new to coding and really need some help.我是编码新手,真的需要一些帮助。

I need to find and copy all those files along 10k+ files together我需要找到所有这些文件并将其复制到 10k+ 个文件中

You claim that the first 3 of your example filenames fit the pattern you describe.您声称示例文件名的前 3 个符合您描述的模式。 I believe that only two do.我相信只有两个人这样做。

@ECHO OFF
SETLOCAL
rem The following setting for the directory is a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.

SET "sourcedir=u:\your files"

FOR /f "delims=" %%e IN (
 'dir /b /a-d "%sourcedir%\A*.tst"^|findstr /X /I /R "A[0-9][0-9][0-9][0-9]_ZZ[a-z][a-z][a-z]_DT[0-9]_F[0-9].tst" '
 ) DO ECHO COPY "%sourcedir%\%%e" X:
)

GOTO :EOF

Always verify against a test directory before applying to real data.在应用于真实数据之前,请始终对照测试目录进行验证。

The required COPY commands are merely ECHO ed for testing purposes.所需的 COPY 命令只是出于测试目的而被ECHO编辑。 After you've verified that the commands are correct , change ECHO COPY to COPY to actually copy the files.确认命令正确后,将ECHO COPY更改为COPY以实际复制文件。 Append >nul to suppress report messages (eg. 1 file copied ) Append >nul以抑制报告消息(例如1 file copied

Simply execute a dir command that reports only filenames matching the *.tst mask.只需执行一个dir命令,它只报告与*.tst掩码匹配的文件名。 Filter this list with findstr which /X exactly matches the regular expression provided.使用findstr过滤此列表,其中/X与提供的正则表达式完全匹配。 findstr only has a limited implementation of regular expressions. findstr仅具有有限的正则表达式实现。 The /I forces a case-insensitive match. /I强制进行不区分大小写的匹配。 If you want case-sensitive, remove the /I and change each [az] to [a-zA-Z] (leave as-is if you want lower-case only in these positions.)如果您想要区分大小写,请删除/I并将每个[az]更改为[a-zA-Z] (如果您只想在这些位置使用小写,请保持原样。)

See findstr /?findstr /? from the prompt for more documentation, or search for examples on SO.从提示获取更多文档,或在 SO 上搜索示例。

---- revision to cater for multiple filemasks and subdirectories --- ---- 修订以适应多个文件掩码和子目录 ---

@ECHO OFF
SETLOCAL
rem The following setting for the directory is a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.

SET "sourcedir=u:\your files"
SET "maskfile=%sourcedir%\q74442552.txt"

FOR /f "tokens=1*delims=" %%e IN (
 'dir /b/s /a-d "%sourcedir%\*.tst"^|findstr /E /I /R /g:"%maskfile%" '
 ) DO ECHO COPY "%%e" X:
)

GOTO :EOF

Changes:变化:

  1. Establish a file, name irrelevant, as maskfile建立一个文件,名字无关紧要,如maskfile
  2. The dir command requires the /s switch to scan subdirectories dir命令需要/s开关来扫描子目录
  3. The filemask for the dir command loses the initial A dir命令的文件掩码丢失了初始A
  4. The findstr command replaces the /X switch with /E findstr命令将/X开关替换为/E
  5. The findstr command loses the regex expression. findstr命令丢失了正则表达式。 These are transferred to a file and the file is nominated by the /g: switch.这些被传输到文件中,文件由/g:开关指定。
  6. The copy command loses the source-directory as the directory will be included in %%e copy命令会丢失源目录,因为该目录将包含在%%e

The file "q74442552.txt" contains lines that are of the form文件“q74442552.txt”包含以下形式的行

A[0-9][0-9][0-9][0-9]_ZZ[a-z][a-z][a-z]_DT[0-9]_F[0-9].tst
A[0-9][0-9][0-9][0-9]_ZZ[a-z][a-z][a-z]_to.*.tst

This time, %%e acquires the full pathname of the files found.这次, %%e获取找到的文件的完整路径名。 Since the filemask ends .tst , the only filenames to pass the dir filter will be those that end .tst .由于文件掩码以.tst结尾,因此只有以.tst结尾的文件名才能通过dir过滤器。

The /e switch tells findstr to match string that E nd with the regex strings in the file specified as /g: . /e开关告诉findstrE nd 的字符串与指定为/g:的文件中的正则表达式字符串进行匹配。

The strings in the file must comply with Microsoft's partial regex implementation, one to a line.文件中的字符串必须符合 Microsoft 的部分regex实现,一个到一行。

In summary, findstr uses as regex总之, findstr用作regex

  • Any character,literally任何字符,字面意思
  • [set] any character of a set of characters [set] 一组字符中的任意字符
  • [^set] any character not in a set of characters [^set] 不在一组字符中的任何字符
  • . . any character任何角色
  • .* any number of any character .* 任意数量的任意字符
  • prefix any of the special characters with \ to use it literally在任何特殊字符前加上\以按字面意思使用它
  • a set may include a range by using low-high一个集合可以包含一个范围,使用low-high

So - you then need to brew-your own using the examples I've supplied.所以 - 然后您需要使用我提供的示例自己酿造。 The second line matches Axxxx_ZZyyy_to{anything}.tst for instance.例如,第二行匹配Axxxx_ZZyyy_to{anything}.tst

--- Minor revision to deal with maintaining destination-tree ----- (see notes to final revision for why this doesn't quite work) --- 处理维护目标树的小修改 ----- (请参阅最终修订说明为什么这不太有效)

@ECHO OFF
SETLOCAL
rem The following setting for the directory is a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.

SET "sourcedir=u:\your files"
SET "maskfile=%sourcedir%\q74442552.txt"
SET "destdir=u:\your results"

FOR /f "tokens=1*delims=" %%e IN (
 'dir /b/s /a-d "%sourcedir%\*.tst"^|findstr /E /I /R /g:"%maskfile%" '
 ) DO ECHO "%%~nxe"&XCOPY /Y /D /S "%sourcedir%\%%~nxe" "%destdir%\">nul
)
   
GOTO :EOF

This version adds the destination root directory as destdir .此版本将目标根目录添加为destdir

The dir... findstr... works as before to list the filenames to copy. dir... findstr...像以前一样工作以列出要复制的文件名。

The prior version used echo copy to report the proposed copy operation, but the destination was always the same directory.以前的版本使用echo copy来报告建议的复制操作,但目标始终是同一目录。

The replacement XCOPY line maintains the directory structure at the destination.替换的XCOPY行在目的地维护目录结构。

Note: the XCOPY is "live".注意: XCOPY是“实时”的。 The files will be copied to the destination if run as-is.如果按原样运行,文件将被复制到目标位置。 Always verify against a test directory before applying to real data.在应用于真实数据之前,请始终对照测试目录进行验证。

To "defuse" the XCOPY , add the /L switch and remove the >nul .要“化解” XCOPY ,请添加/L开关并删除>nul This will cause XCOPY to report the source name that would be copied instead of copying it.这将导致XCOPY报告将被复制的源名称而不是copying它。 (The >nul suppresses the report) >nul禁止报告)

The /D only copies source files that eitherr do not exist in the destination of have a later datestamp in the source. /D仅复制目标中不存在或源中具有较晚日期戳的源文件。

The action is to xcopy each file name found ( %%~nxe ) from the source directory tree to the destination.该操作是将找到的每个文件( %%~nxe xcopy从源目录树复制到目标。 Therefore, any file xyz.tst found anywhere in the source tree will be xcopy d to the destination tree.因此,在源树中任何位置找到的任何文件xyz.tst都将被xcopy d 到目标树。 The /D means that once xyz.tst is encountered on the source tree, it will be skipped should it be encountered again. /D意味着一旦在源代码树上遇到xyz.tst ,如果再次遇到它,它将被跳过。

--- Final (I hope) revision --- ---最终(我希望)修订---

@ECHO OFF
SETLOCAL
rem The following setting for the directory is a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.

SET "sourcedir=U:\Users\tocil\Desktop\aoi"
SET "maskfile=%sourcedir%\q74442552.txt"
SET "destdir=u:\your results"

FOR /f "tokens=1*delims=" %%e IN (
 'dir /b/s /a-d "%sourcedir%\*.tst"^|findstr /E /I /R /g:"%maskfile%" '
 ) DO (
  rem drive and path to 'dirname' - has terminal "\"
  SET "dirname=%%~dpe"
  rem remove the sourcedir from dirname
  FOR %%y IN ("%sourcedir%") DO CALL SET "dirname=%%dirname:%%~y=%%"
  rem copy or xcopy the file to the destination. 
  FOR /f "tokens=2delims==" %%y IN ('set dirname') DO XCOPY /Y "%%e" "%destdir%%%y">nul
 )
)

GOTO :EOF

Always verify against a test directory before applying to real data.在应用于真实数据之前,请始终对照测试目录进行验证。

Note to self: Only if the filemask provided to XCOPY is ambiguous (ie. contains ? or * ) will XCOPY obey the /s switch unless the target file exists in the starting source directory.自我注意:只有当提供给XCOPY的文件掩码不明确(即包含?* )时,XCOPY 才会服从/s开关,除非目标文件存在于起始源目录中。

hence因此

xcopy /s sourcedir\myfile destdir

will copy myfile from the entire tree ONLY if sourcedir\myfile exists.sourcedir\myfile存在时,才会从整个树中复制myfile

xcopy /s sourcedir\myf?le destdir

will copy myfile from the entire tree regardless.无论如何都会从整个树中复制myfile Unfortunately it will also copy myfale and myfule as well.不幸的是,它也会复制myfalemyfule

Hence, the new approach.因此,新方法。

First, perform a dir /b /s to get all of the filenames and filter as before.首先,执行dir /b /s以获取所有文件名并像以前一样进行过滤。 This is being assigned to %%e .这被分配给%%e

Take the drive and path only of the file and assign to dirname .仅获取文件的驱动器和路径并分配给dirname

The next step is a little complex.下一步有点复杂。 First, set the value of %%y to the name of the source directory.首先,将%%y的值设置为源目录的名称。 Next, use a parser trick to remove that name from dirname .接下来,使用解析器技巧从dirname中删除该名称。 The mechanics are: Parse the %%dirname:%%~y=%% (because the call causes the set to be executed in a sub-shell) whuch does the normal left-to-right evaluation.机制是:解析%%dirname:%%~y=%% (因为call导致set在子 shell 中执行),它执行正常的从左到右的评估。 %% is an escaped-%, so is replaced by % ; %%是一个转义的%,所以被替换为% %%y is an active metavariable so is replaced by (the name of the source directory) and the ~ causes the quotes to be stripped from that name. %%y是一个活动的元变量,因此被替换为(源目录的名称)并且~导致从该名称中删除引号。 The resultant command executed is thus SET "dirname=%dirname:nameofsourcedirectory=%"因此,执行的结果命令是SET "dirname=%dirname:nameofsourcedirectory=%"

So now we can construct a copy -class instruction.所以现在我们可以构造一个copy类指令。 dirname now contains the relative directory for the destination, which we can extract from the environment by parsing a set listing (Could also be done with delayed expansion ) where %%y gets set to the relative directory and has both a leading and trailing backslash, so the destination directory is simply "%destdir%%%y" . dirname现在包含目标的相对目录,我们可以通过解析set列表(也可以通过delayed expansion来完成)从环境中提取它,其中%%y被设置为相对目录并且有一个前导和尾随反斜杠,所以目标目录只是"%destdir%%%y" XCOPY then knows to create that directory if necessary ( %%y has a trailing backslash) and we know the source filename is in %%e . XCOPY然后知道在必要时创建该目录( %%y有一个尾随反斜杠)并且我们知道源文件名在%%e中。

You could also use a copy to do the same thing, but you'd need to create the destination directory first.您也可以使用copy来做同样的事情,但您需要先创建目标目录。 Another advantage of XCOPY is that you can also specify the /d switch to not copy files that have an earlier date over files that have a later date. XCOPY的另一个优点是您还可以指定/d开关以不复制日期较早的文件覆盖日期较晚的文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM