想到一个情景。程序实时监测文件夹情况,如果有新文件进入,分析其文件名,然后如果满足预设条件,则做相应操作。比如扫描仪扫描了文件,会将新文件保存进特定文件夹内,可以使用该程序来做处理。

在Windows端最直接的就是用.bat批处理,当然使用Powershell或者C#、python语言平台更轻松专业,这里使用 .bat 实现。笔者喜欢窗口下,看着字符串一行行打印出来的感觉,啊哈哈~~~

【设计需求】

使用cmd实现:检测文件夹(D:\projects\cmd\targetdir) 内是否有新文件出现,如果有,查看该文件的文件名,如果是以A字符打头的,那么将该文件发送给远程文件夹(\\DESKTOP-JL8BQNM\temp4share) 程序不断地去检测,注意生成日志方便调式和日后维护。

【设计思路】

1.  要想监测文件夹内是否有新文件,需要对比当前的文件列表和之前的文件列表,如果有出入,则有增添删减文件

2.   把新文件名称记录下来,解析字符并做比较,得出满足条件的文件对象。

3.  将满足条件的文件拷贝到远程文件夹中。其中远程通讯需要双方都开启共享。

4.  每个关键操作需要概括为描述性字符,写入日志文件中。

5.  程序需要有死循环机制,让其不断监测,Ctrl+C 可退出。

【设计脚本】

首先必要的变量先定义好:

set "script_dir=%~dp0"    %定义当前脚本目录%
set "target_dir=D:\projects\cmd\targetdir" %定义监测的目录地址%
set "remote_dir=\\DESKTOP-JL8BQNM\temp4share" %定义远程的目录地址%
set "log_file=%script_dir%FileMonitor.log" %日志文件存放地址%
set "check_interval=5" %重新执行的间隔时间 5秒%

之后编写cmd界面,做必要解释:

echo ================================================
echo █ 文件监控传输工具 █
echo ================================================
echo [版本特性]
echo √ 严格匹配大写A开头文件 √ 特殊字符支持
echo √ 实时传输状态提示 √ 详细日志记录
echo 监控目录 : "%target_dir%"
echo 远程目录 : "%remote_dir%"
echo 日志文件 : "%log_file%"
echo 检测间隔 : 每%check_interval%秒
echo ================================================
echo [注意] 大文件传输时会暂停监控,保持窗口开启
echo 按 Ctrl+C 安全终止程序
echo ================================================

然后,编写核心算法:

:: 生成初始文件快照
dir /b "%target_dir%" > "%script_dir%prevfiles.txt"

再次生成文件快照,和之前的作对比:

dir /b "%target_dir%" > "%script_dir%currentfiles.txt"
findstr /v /g:"%script_dir%prevfiles.txt" "%script_dir%currentfiles.txt" > "%script_dir%newfiles.txt"

如果有新增文件,做对应处理:

for /f "usebackq tokens=*" %%f in ("%script_dir%newfiles.txt") do (
call :process_file "%%~f"
)

提取文件名首字母:

set "first_char=!filename:~0,1!"

然后做判断,如果符合首字母"A",则做拷贝操作,如果不是忽略文件:

if "!first_char!"=="A" (
color 0A
echo 符合条件:大写A开头文件
echo 开始传输,请勿关闭窗口... :: 使用robocopy增强传输(显示进度但保持静默)
robocopy "%target_dir%" "%remote_dir%" "!filename!" /njh /njs /ndl /nc /np :: 错误代码处理(ROBOCOPY特有代码)
if errorlevel 8 (
color 0C
echo [严重错误] 代码!errorlevel! 磁盘空间不足
echo [%timestamp%] ERROR: 传输失败 → "!safe_filename!" [代码!errorlevel!] >> "%log_file%"
) else if errorlevel 4 (
color 0E
echo [警告] 代码!errorlevel! 文件不匹配
echo [%timestamp%] WARN: 传输异常 → "!safe_filename!" [代码!errorlevel!] >> "%log_file%"
) else if errorlevel 1 (
color 0A
echo [成功] 传输完成
echo [%timestamp%] SUCCESS: 已传输 → "!safe_filename!" >> "%log_file%"
)
color 0F
) else (
echo 忽略:非大写A开头文件
echo [%timestamp%] INFO: 忽略文件 → "!safe_filename!" >> "%log_file%"
)

因为想要生成日志,因此每做一个操作,获取时间并输入给 .log。

:get_timestamp
for /f "tokens=2 delims==." %%t in ('wmic os get localdatetime /value 2^>nul') do set "datetime=%%t"
set "timestamp=!datetime:~0,4!-!datetime:~4,2!-!datetime:~6,2! !datetime:~8,2!:!datetime:~10,2!:!datetime:~12,2!"

另外想要不断监测,程序需要循环执行:

rem ...
:: ==================== 主监控循环 =====================
:monitor_loop
call :get_timestamp rem ... :: 间隔检测(非阻塞等待)
timeout /t %check_interval% /nobreak >nul
goto monitor_loop

还有一些细节:

使用robocopy命令传输:

robocopy "%target_dir%" "%remote_dir%" "!filename!" /njh /njs /ndl /nc /np /ns /nfl
if errorlevel 8 (
...错误处理...
)

更科学更安全,提升特殊字符处理能力,也可以返回错误信息。

  • ROBOCOPY错误代码表

代码 含义 处理建议
0 无变化 正常情况
1 文件复制成功 记录日志
4 不匹配文件 检查文件系统
8 磁盘空间不足 紧急处理
16 无效参数 检查脚本配置

因此可以对错误码进行逐一对比操作:

 :: 错误代码处理(ROBOCOPY特有代码)
if errorlevel 8 (
color 0C
echo [严重错误] 代码!errorlevel! 磁盘空间不足
echo [%timestamp%] ERROR: 传输失败 → "!safe_filename!" [代码!errorlevel!] >> "%log_file%"
) else if errorlevel 4 (
color 0E
echo [警告] 代码!errorlevel! 文件不匹配
echo [%timestamp%] WARN: 传输异常 → "!safe_filename!" [代码!errorlevel!] >> "%log_file%"
) else if errorlevel 1 (
color 0A
echo [成功] 传输完成
echo [%timestamp%] SUCCESS: 已传输 → "!safe_filename!" >> "%log_file%"
)

还有特殊字符  &  的处理

set "safe_filename=!filename:^&=^^^&!"

避免文件名称有特殊字符。(实际上作为文件名,本身不允许特殊字符,这里做保险之用)

另外

@echo off:关闭命令回显,提升界面整洁度

setlocal enabledelayedexpansion:启用延迟变量扩展,正确处理动态变量,始终在脚本开头使用setlocal防止污染系统环境变量

title:自定义控制台窗口标题

color 0F & cls:设定白色文本并清空内容

还有时刻注意做日志备份信息。如:

echo [%timestamp%] INFO: 发现文件 → "!safe_filename!" >> "%log_file%"

完整脚本代码如下:

@echo off
setlocal enabledelayedexpansion
title 文件监控传输工具 V1.4 :: ======================= 配置参数 ========================
set "script_dir=%~dp0" & rem 获取脚本所在目录
set "target_dir=D:\projects\cmd\targetdir" & rem 监控目录
set "remote_dir=\\DESKTOP-JL8BQNM\temp4share" & rem 远程目录
set "log_file=%script_dir%FileMonitor.log" & rem 日志文件路径
set "check_interval=5" & rem 检测间隔(秒) :: ====================== 初始化界面 =======================
color 0F & cls
echo ================================================
echo █ 文件监控传输工具 █
echo ================================================
echo [版本特性]
echo √ 严格匹配大写A开头文件 √ 特殊字符支持
echo √ 实时传输状态提示 √ 详细日志记录
echo 监控目录 : "%target_dir%"
echo 远程目录 : "%remote_dir%"
echo 日志文件 : "%log_file%"
echo 检测间隔 : 每%check_interval%秒
echo ================================================
echo [注意] 大文件传输时会暂停监控,保持窗口开启
echo 按 Ctrl+C 安全终止程序
echo ================================================ :: ================== 文件列表初始化 ====================
dir /b "%target_dir%" > "%script_dir%prevfiles.txt" :: ==================== 主监控循环 =====================
:monitor_loop
call :get_timestamp
echo [%timestamp%] 扫描进行中... :: 生成当前文件列表(安全模式)
dir /b "%target_dir%" > "%script_dir%currentfiles.txt" :: 检测新增文件(增强模式)
findstr /v /g:"%script_dir%prevfiles.txt" "%script_dir%currentfiles.txt" > "%script_dir%newfiles.txt" :: 处理新增文件(支持特殊字符)
for /f "usebackq tokens=*" %%f in ("%script_dir%newfiles.txt") do (
call :process_file "%%~f"
) :: 更新文件列表缓存
move /y "%script_dir%currentfiles.txt" "%script_dir%prevfiles.txt" >nul
del "%script_dir%newfiles.txt" 2>nul :: 间隔检测(非阻塞等待)
timeout /t %check_interval% /nobreak >nul
goto monitor_loop :: ================== 文件处理模块 =====================
:process_file
set "filename=%~1"
set "safe_filename=!filename:^&=^^^&!" & rem 转义特殊字符 :: 获取首字符(ASCII值方式更可靠)
set "first_char=!filename:~0,1!"
call :get_timestamp :: 日志记录(双重写入)
echo [%timestamp%] 发现文件: "!safe_filename!"
echo [%timestamp%] INFO: 发现文件 → "!safe_filename!" >> "%log_file%" :: ============ 严格大写A检测(ASCII值65) =============
if "!first_char!"=="A" (
color 0A
echo 符合条件:大写A开头文件
echo 开始传输,请勿关闭窗口... :: 使用robocopy增强传输(显示进度但保持静默)
robocopy "%target_dir%" "%remote_dir%" "!filename!" /njh /njs /ndl /nc /np :: 错误代码处理(ROBOCOPY特有代码)
if errorlevel 8 (
color 0C
echo [严重错误] 代码!errorlevel! 磁盘空间不足
echo [%timestamp%] ERROR: 传输失败 → "!safe_filename!" [代码!errorlevel!] >> "%log_file%"
) else if errorlevel 4 (
color 0E
echo [警告] 代码!errorlevel! 文件不匹配
echo [%timestamp%] WARN: 传输异常 → "!safe_filename!" [代码!errorlevel!] >> "%log_file%"
) else if errorlevel 1 (
color 0A
echo [成功] 传输完成
echo [%timestamp%] SUCCESS: 已传输 → "!safe_filename!" >> "%log_file%"
)
color 0F
) else (
echo 忽略:非大写A开头文件
echo [%timestamp%] INFO: 忽略文件 → "!safe_filename!" >> "%log_file%"
) echo --------------------------------------------------------
exit /b :: ================== 时间戳生成模块 ====================
:get_timestamp
for /f "tokens=2 delims==." %%t in ('wmic os get localdatetime /value 2^>nul') do set "datetime=%%t"
set "timestamp=!datetime:~0,4!-!datetime:~4,2!-!datetime:~6,2! !datetime:~8,2!:!datetime:~10,2!:!datetime:~12,2!"
exit /b endlocal

【设计小结】

后期还可以优化程序,比如可以引入配置文件----config.ini,如:

[Settings]
TargetDir=D:\projects\cmd\targetdir
RemoteDir=\\DESKTOP-JL8BQNM\temp4share
CheckInterval=5

还有,对于转义算法,为了处理文件名称带有&字符:

set "safe_filename=!filename:^&=^^^&!"

!filename:原字符串=新字符串! 表示对变量 filename 进行字符串替换。

原字符串 是 ^&(实际匹配 & 符号)

新字符串 是 ^^^&(实际生成转义后的 ^&

转义逻辑:

原字符串 中的 ^&^ 在这里是转义符,表示要匹配实际的 & 符号。

新字符串 中的 ^^^&:第一个 ^ 转义第二个 ^,生成一个普通 ^,第三个 ^ 转义 &,生成 ^&

当然该操作仅转义了 & 符号,其他特殊字符如 |>< 仍需额外处理。

不过正常情况下,文件名称不应该出现特殊字符,所以不用深究。

还有对于:

for /f "usebackq tokens=*" %%f in ("%script_dir%newfiles.txt") do (

为了防止反引号和括号给文本处理带来干扰。

usebackq参数是为了反引号的正常处理,"%script_dir%newfiles.txt",加上双引号,防止括号被解析为命令的一部分,建议所有路径操作强制使用引号包裹,避免解析错误。

还可优化的部分:

1.  临时的prevfiles.txt文件可以不用展现出来,在退出程序前将其消除。

2.  拷贝文件实际上是阻塞程序继续监测的,如果可以,设置成非阻塞的。

3.  设置日志轮转,更科学得管理日志。

脚本可以作为一个轻量级解决方案案例,展现了实时监控逻辑的实现范式,为复杂系统开发提供了基础设计模式参考。希望给读者一些灵感。CMD,你老爹永远是你老爹~~~~

批处理脚本(.bat)实现实时监测文件夹并执行命令 [假设有新文件则拷贝到远程文件夹内]的更多相关文章

  1. 根据随身固态U盘卷标搜索U盘盘符并打开文件的批处理脚本.bat 徐晓亮 595076941@qq.com 2019年12月19日6点50分

    @Echo offRem 根据随身固态U盘卷标搜索U盘盘符并打开文件的批处理脚本.batRem 徐晓亮 595076941@qq.com 2019年12月19日6点50分 Rem 此批处理脚本源代码的 ...

  2. 01_安装电脑软件的步骤批处理脚本.bat

    REM 01_安装电脑软件的步骤批处理脚本.bat MD 01_安装电脑软件的步骤 REM ZIP解压密码空格MD 02_制作杏雨梨云USB维护系统2019中秋版之国庆更新固态U盘MD 03_复制安装 ...

  3. Perl脚本通过Expect登陆多台设备批量执行命令并Log

    本例子尝试使用Perl脚本借助Expect模块实现如下目的: 登陆多台设备 设备登陆信息按如下格式存放于文件中. $ cat hosts.txt 192.168.30.7:node1:telnet:b ...

  4. python连接服务器上传文件,后台执行命令

    上传文件 import os import paramikoimport logging from django.core.cache import cache from YunTai import ...

  5. 配置windows批处理脚本(.bat)文件路径 | window批处理文件配置执行路径

    以PHP的composer为例 1 . 路径D:\phpStudy\php\php-5.5.38加入环境变量 2.在路径D:\phpStudy\php\php-5.5.38新建composer.bat ...

  6. 【SQLite】批处理脚本BAT读取SQLite数据

     批处理读写SQLite数据库.bat:(编码ANSI) @echo off sqlite3 "F:\improve\SQLite\BAT\Test.db" <"F ...

  7. shell遍历文件夹并执行命令

    背景: 有一个源码包里面包含很多子目录和makefile,打包后的压缩包太大,需要将make生成的所有二进制文件删除然后再打包. 需求: 因此,要求在制定目录的所有递归子目录中执行make clean ...

  8. 使用批处理文件(.bat)启动多个CMD窗口并执行命令

    由于每次启动本机的kafka都需要打开2个cmd窗口,分别启动zookeeper服务和kafka服务,操作相对繁琐,于是想起了批处理来帮忙一键启动. 在桌面新建一个txt文件,改后缀名为.bat,并加 ...

  9. mac 查找当前目录下所有同一类型文件,并执行命令行

    以TexturePacker举例 MAC下用TexturePacker命令行打包当前目录下所有的 *.tps文件 1.配置好tps文件需要配置好路径.参数等.(也可不配置,用命令行实现.具体参考:ht ...

  10. shell 脚本实战笔记(8)--ssh免密码输入执行命令

    前言: ssh命令, 没有指定密码的参数. 以至于在脚本中使用ssh命令的时候, 必须手动输入密码, 才能继续执行. 这样使得脚本的自动化执行变得很差, 尤其当ssh对应的机器数很多的时候, 会令人抓 ...

随机推荐

  1. CompilerGenerated与GeneratedCode区别

    前言 最近在捣鼓代码生成器,基于 Roslyn,我们可以让生成器项目生成我们的目标 C# 代码,这个也是MVVM Toolkit的实现方式,在查看生成代码的过程中,我们经常会遇到一些特殊的特性,如 G ...

  2. Vulnhub经典靶机:from_sqli_to_shell_i386入门靶机

    靶机官网: https://www.vulnhub.com/entry/pentester-lab-from-sql-injection-to-shell,80/ 靶机镜像ISO下载地址:(转链) f ...

  3. arch 音频处显示没有输入或输出设备

    我的设备是 Dell G15 5511, 属于比较新的设备, 查看了 Fourm 与 wiki 后使用 1 yay -S sof-firmware   安装框架之后重启即可使用.

  4. Qt编写的项目作品25-硬件综合应用(热敏打印+身份证+短信猫)

    一.功能特点 (一).串口热敏打印 标准热敏打印协议解析,无依赖,支持任意系统. 可打印各种文字信息比如访客单.报警信息等. 可打印条形码即一维码. 可打印二维码,设置二维码尺寸. 支持多线程打印图片 ...

  5. 计算机视觉中由基本矩阵F或者本质矩阵E计算摄像机投影矩阵时,经常提到“相差一个尺度因子”的含义

    在通过二维像素坐标恢复三维坐标的过程中,经常出现这个齐次坐标系.尺度不变性的概念.这篇博客讲的比较好. 一.关于齐次坐标系的直观感受 在我们的世界里,两平行线是永远不会相交的,但是在投影空间里,两条平 ...

  6. ArrayList源码解析-JDK18

    引言 ArrayList在JDK1.7和1.8中的差距并不大,主要差距以下几个方面: JDK1.7 在JDK1.7中,使用ArrayList list = new ArrayList()创建List集 ...

  7. ArrayBlockingQueue源码剖析

    生产者-消费者ArrayBlockingQueue是一个实现了BlockingQueue接口的类,其可以很方便的实现生产者-消费者模式.用法如下: class Producer implements ...

  8. leetcode-Linux 简介

    https://leetcode-cn.com/leetbook/read/awesome-linux-handbook/eg4ecm/ Linux 系统是一种金字塔模型的系统,如下所示 应用程序发起 ...

  9. java设计模式---总则

    设计模式总则 一.概述 1.什么是设计模式 设计模式是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 解释下: 分类编目:就是说可以找到一些特征去划分这些设计模式,从而进行分类. ...

  10. 【隐私计算笔谈】MPC系列专题(十):安全多方计算下的集合运算

    学习&转载文章:[隐私计算笔谈]MPC系列专题(十):安全多方计算下的集合运算 集合运算 集合可以通俗地描述为确定的一堆东西.如有一个集合\(\),一个元素\(\)要么属于集合\(\),记做\ ...