Windows下文件批量复制踩坑实录

前景提要

在服务器日常维护工作中,因为用户或者同事要批量导出附件用作数据分析或者工作汇报,会提供一个文件列表,文件列表里面的附件不在同一个目录,并且也不会完全复制同一个目录下面的所有文件。不同于网上其他的从一个目录批量复制文件到另一个目录,本文章讲的是通过遍历列表,按需复制文件到指定目录。

附件列表格式

这里举个例子说一下附件列表的形式,是一个txt文件,在这里就叫1.txt吧,链接已经过脱敏处理,所以看起来会很怪。

K:/dcsgs/ppy/051zz/01zzfile/axcazppy2cgbgzz.file
K:/dcsgs/kk/axc222az/ppy02-20071730/051zz/01zzfile/azcv2.file
K:/dcsgs/kk/axc222az/ppy02-20071730/051zz/01zzfile/azcv22.file
K:/dcsgs/s2fhg/vew3baz/ppy/051zz/01zzfile/vew3bazdf32cv2.file
K:/dcsgs/s2fhg/vew3baz/ppy/051zz/01zzfile/vew3bazdf32cv21.file
K:/aa/s2fhg/vew3baz/ppy/051zz/02asfile/01ppy2cgbgfv232cgbg/083dvgf3.file
K:/aa/s2fhg/vew3baz/ppy/051zz/02asfile/01ppy2cgbgfv232cgbg/073dvgf2cgbgfv23.file
K:/aa/s2fhg/vew3baz/ppy/051zz/02asfile/01ppy2cgbgfv232cgbg/03df32file.file
K:/aa/s2fhg/vew3baz/ppy/051zz/02asfile/01ppy2cgbgfv232cgbg/01qq.file
K:/aa/s2fhg/vew3baz/ppy/051zz/02asfile/02as/01CAD/17dc2.file
K:/qdv/s2fhg/vew3baz/ppy/051zz/02asfile/02as/01CAD/1412cppy.file
K:/qdv/s2fhg/vew3baz/ppy/051zz/032file/01a/043dvgfss4.10.file
I:/ds/a12f/a12f2az/ppy/051zz/032ffile/28qdsf/01CAD/13242.file
I:/ds/a12f/a12f2az/ppy/051zz/032ffile/28qdsf/01CAD/11.file
I:/ds/a12f/a12f2az/ppy/051zz/032ffile/28qdsf/01CAD/121.file
I:/ds/a12f/a12f2az/ppy/051zz/02asfile/01ppy2cgbgfv232cgbg/d.file
I:/ds/a12f/a12f2az/ppy/051zz/02asfile/01ppy2cgbgfv232cgbg/11.file
I:/ds/a12f/a12f2az/ppy/051zz/02asfile/02as/02file/a.file

每一个都列清楚了文件所处位置,每个文件夹里面只取指定文件,其他都不取出,总体分为K盘和I盘,是两个盘。

之前的写法

我手里有几个其他同事写的脚本,在Windows Server 2008环境下使用的非常顺。
这些CMD脚本分两种思路,一种是遍历附件列表1.txt,进行for循环处理;一种是通过excel处理附件列表,批量生成每个文件的复制命令。第二种太不程序员了,这里只说第一种。

@echo off
for /f "delims=" %%a in ('type "1.txt"') do "C:\Windows\System32\xcopy.exe" "%%a" "F:\20211111\i\%%~pa" /s /y
pause

直接用xcopy复制,并用%%a获取文件名,%%~pa获取文件掐头去尾的路径。

注意这里%%~pa,除了p是获得路径,目前已知n,x,d都有自己的功能,可以试一下。
做这个的时候就参考了 https://blog.csdn.net/qhs1573/article/details/100524255 里面对批处理截取字符的运用,但是还没人系统归纳过

遇到的问题

以前知道PowerShell在Windows Server的2008/2012/2016上,都要各写一套,在2012上写的,在2008和2016运行都有问题,今天发现CMD也有这样的问题,微软是真的很离谱。
现象就是运行上述代码只创建文件夹不创建文件。
于是经过各种坑,最终分拆了1.txt为k.txt和i.txt,分别存了两个盘的路径,并写了如下的代码。

@echo off
for /f "delims=" %%a in ('type "E:\aaaa\k.txt"') do (
    if not exist "E:\bbbbb%%~pa" mkdir "E:\bbbbb%%~pa"
    copy "\\192.168.101.100\ak1%%~pa%%~nxa" "E:\bbbbb%%~pa%%~nxa"
)
for /f "delims=" %%a in ('type "E:\aaaa\i.txt"') do (
    if not exist "E:\ccccc%%~pa" mkdir "E:\ccccc%%~pa"
    copy "\\192.168.101.105\qq_1\qqq_1%%~pa%%~nxa" "E:\ccccc%%~pa%%~nxa"
)
pause

说明一下意思,在服务器上K盘和I盘是两个盘,分别对应的是\\192.168.101.100\ak1和\\192.168.101.105\qq_1\qqq_1。
遇到哪些坑呢?

  1. 在Windows Server 2008上可以直接通过挂盘盘符访问文件,比如K:/dcsgs/ppy/051zz/01zzfile/axcazppy2cgbgzz.file,但是现在在2016上必须使用\192.168.101.100\ak1/dcsgs/ppy/051zz/01zzfile/axcazppy2cgbgzz.file访问。
  2. 不要使用传参。由于需要拼接附件名,中间为了DEBUG,对参数使用了赋值并echo,赋值命令形如set SOURCEPATH="\\192.168.101.100\ak1%%~pa%%~nxa"这样,但是echo %SOURCEPATH%会出现第一次赋值失败,第二次赋值成功的奇葩现象,一样的脚本不一样的结果,因此取消了中间传参过程。
  3. %%~pa是掐头去尾的中间路径,后面还需要拼接文件名。但是%%~na显示的是无文件后缀的文件名,必须用%%~nxa才能显示文件名加后缀名,不知道%%~pnxa是不是可以直接满足%%~pa%%~na拼接的需求,如果有哪位同学尝试了,请留言这样做是否可以。
  4. copy不一定能新建文件夹,所以需要先创建文件夹后copy,所以才加了if not exist "E:\ccccc%%~pa" mkdir "E:\ccccc%%~pa"这个语句。

更新

补充:其实修改附件文件

K:/dcsgs/ppy/051zz/01zzfile/axcazppy2cgbgzz.file
# 把/改成\
K:\dcsgs\ppy\051zz\01zzfile\axcazppy2cgbgzz.file

就可以用

@echo off
for /f "delims=" %%a in ('type "1.txt"') do "C:\Windows\System32\xcopy.exe" "%%a" "F:\20211111\i\%%~pa" /s /y
pause

另外还有看到其他写法,比如借助excel直接枚举所有文件的,也是一个不错的方式

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值