bat批处理遍历指定目录下文件并更新

前言

先来看这样一个需求,假设有A,B两个目录,其中A目录是资源目录,B目录是工作目录,其中资源目录不定期更新,资源文件都在A目录下,并且没有子目录层级关系,但是资源要被使用时需要更新到B工作目录,B目录根据工程需要建立了一个包含众多子目录的层级体系,这样当A目录中的一个资源文件更新后,需要手动复制A目录中更新的资源文件,然后在B目录中找到对应的位置,然后进行粘贴替换,这样的操作如果很久一次、或者每次只有1、2个文件还好,如果资源文件大范围更新,那么要一个个找到更新文件在B目录中的位置然后替换就成了一件令人苦恼的事情,所以根据这个需求,才有了下面的探索过程。

思路的转变

一开始想把A目录作为出发点,毕竟A目录中包含了修改后的资源文件,但是A目录更新后怎样才能准确的修改对应的B目录呢?我想到了配表,每次新增资源后,都会修改配置表,将A目录中的各个文件资源与B目录中的位置建立对应关系,这样A目录下的资源更新后就可以根据配置文件统一更新B目录了。

但这样的做法就是,需要经常维护配置文件,特别是增加或者删除资源的时候,然后我就想到了现在的这个做法,从B目录出发,注意本文主要解决的是资源文件的更新,而不是新增,更新就说明是原有的文件,只是内容发生了变化,比如一些UI文件,这些文件经常会做布局格式的调整,控件的增加和删除等等,调整结束后需要更新到工作目录。

实现过程

实现的过程并没有想象的那么顺利,期间遇到了诸多问题和一些新的概念,比如for循环的语法,for循环中的变量定义,if条件的语法,字符串变量的替换,文件目录的处理,延迟环境变量扩展等等,这些问题每一项都可以作为一个单独的知识点,后续我会抽时间慢慢总结到一起,总之最后终于可以用了,前后大约花了1个半小时的时间,想想也是醉了,下面是一个具体的示例及对应的实现代码。

  1. A资源目录对应实际的”E:/dirZ”,结构如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    root:[E:/dirZ]
    +--aaa.txt
    +--bbb.txt
    +--ccc.txt
    +--ddd.txt
    +--eee.txt
    +--extra.c
    +--extra.h
    +--fff.txt
    +--ggg.txt
  2. B工作目录对应实际的”E:/dirA”,结构如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    root:[E:/dirA]
    +--aaa.txt
    +--bbb.txt
    +--dirB
    | +--ccc.txt
    | +--extra.c
    | +--extra.h
    +--dirC
    | +--ddd.txt
    | +--dirD
    | | +--eee.txt
    +--dirE
    | +--dirF
    | | +--fff.txt
    | | +--ggg.txt
  3. 现在需要把E:/dirZ目录中的txt文件,按照E:/dirA目录的层级结构,更新到对应位置,并且不更新ggg.txt文件,以下是实现的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    @echo off

    rem 启用延迟环境变量扩展
    setlocal enabledelayedexpansion

    rem 定义不需要更新的文件
    SET EXCEPT_FILE=ggg.txt

    rem 定义工作目录和资源目录
    SET WORK_PATH=E:\dirA\
    SET RESO_PATH=E:\dirZ\

    rem 简单输出查看一下
    echo WORK_PATH is %WORK_PATH%
    echo RESO_PATH is %RESO_PATH%
    echo ------------------------

    rem for循环递归遍历WORK_PATH目录中的.txt文件,文件的全路径放在变量f中
    for /R %WORK_PATH% %%f in (*.txt) do (
    rem 使用TARGET_FILE变量记录绝对文件名,注意延迟变量的使用
    SET TARGET_FILE=%%f
    echo !TARGET_FILE!

    rem 去掉路径,只保留文件名及扩展名
    SET "FILE_PATH_NO_EXT=%%~nxf"
    rem 利用资源路径和文件名,拼接出资源的绝对全路径
    SET SOURCE_FILE=%RESO_PATH%!FILE_PATH_NO_EXT!
    echo !SOURCE_FILE!

    rem 条件判断是否是不需要更新的文件
    if NOT !FILE_PATH_NO_EXT!==%EXCEPT_FILE% (
    copy !SOURCE_FILE! !TARGET_FILE!
    )
    )
    pause
  4. 运行结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    WORK_PATH is E:\dirA\
    RESO_PATH is E:\dirZ\
    ------------------------
    E:\dirA\aaa.txt
    E:\dirZ\aaa.txt
    已复制 1 个文件。
    E:\dirA\bbb.txt
    E:\dirZ\bbb.txt
    已复制 1 个文件。
    E:\dirA\dirB\ccc.txt
    E:\dirZ\ccc.txt
    已复制 1 个文件。
    E:\dirA\dirC\ddd.txt
    E:\dirZ\ddd.txt
    已复制 1 个文件。
    E:\dirA\dirC\dirD\eee.txt
    E:\dirZ\eee.txt
    已复制 1 个文件。
    E:\dirA\dirE\dirF\fff.txt
    E:\dirZ\fff.txt
    已复制 1 个文件。
    E:\dirA\dirE\dirF\ggg.txt
    E:\dirZ\ggg.txt
    请按任意键继续. . .

总结

到此为止我们就解决了这个资源更新的实际问题,每次资源更新后只要运行这个批处理文件就可以更新工作目录中对应的资源文件了,在这个例子中关于目录的截取,一开始走了很多弯路,其实有很多现成的方式,所以需要在此记录一下,方便以后查找使用,具体查看示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ECHO off
SETlOCAL enabledelayedexpansion

SET FIND_DIR=E:\dirA\dirC\dirD

for /R %FIND_DIR% %%f in (*.txt) do (
SET FULL_PATH=%%f
ECHO 完整的路径: !FULL_PATH!

SET FILE_DIR=%%~dpf
ECHO 所在的目录: !FILE_DIR!

SET FILE_NAME=%%~nf
ECHO 无后缀文件: !FILE_NAME!

SET FILE_EXT=%%~xf
ECHO 文件名后缀: !FILE_EXT!

SET "FILE_NAME_NOT_PATH=%%~nxf"
ECHO 无路径文件: !FILE_NAME_NOT_PATH!

SET "FULL_PATH_NOT_EXT=%%~dpnf"
ECHO 无后缀全名: !FULL_PATH_NOT_EXT!
)
pause

运行结果:

1
2
3
4
5
6
完整的路径: E:\dirA\dirC\dirD\eee.txt
所在的目录: E:\dirA\dirC\dirD\
无后缀文件: eee
文件名后缀: .txt
无路径文件: eee.txt
无后缀全名: E:\dirA\dirC\dirD\eee
Albert Shi wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客