Windows批处理脚本编写学习


=Start=

缘由:

前段时间因为工作需要简单学习了一下Windows上batch脚本的编写,已经可以用batch脚本实现一些简单的常用功能,这里简要记录一下,方便以后有需要的时候进行参考。

正文:

参考解答:

起因在于我有一个Windows软件下发安装的需求,但现在软件下发通道那里做的还比较糙,没办法进行一些细粒度的判断和控制,要安装的软件本身也不是特别“智能”,这时我就需要自己写一个batch脚本来实现判断是否安装、比较安装版本、下载安装文件、上报安装结果和状态的功能。下面就简单记录一下在实现这个功能时的拆解和搜索过程,方便后面参考。

简单来看常规操作就是以下几点:

  • 要知道获取相关信息的命令是什么(比如获取IP用ipconfig命令)
  • 管道/重定向
  • 文件操作(创建/打印/复制/删除/压缩/解压/……)
  • 字符串查找/截取/比较/拼接/切分/……
  • 网络请求
Windows 命令行/batch脚本中如何获取主机系统相关信息?

IP/MAC地址
主机名
操作系统版本
序列号

如果仅仅只是在命令行上面看的话都还比较简单直接:

ipconfig /all
hostname
wmic os get caption
wmic bios get serialnumber

不过如果想把具体的值通过接口进行上报的话就需要进行字符串提取和格式化,Windows上原生的命令/batch脚本处理能力相对Linux要弱很多(主要是Windows的我不熟,PowerShell也不会而且貌似也存在版本差异?),处理起来就麻烦了不少。

比如:for命令的功能有限且限制较多,没办法在 command 那里使用管道操作符,只能先将复合命令的结果重定向到文件里面,然后处理文件内容,这里就涉及到字符串处理了——字符串查找/提取/拼接……Linux上几行命令就能完成的功能在Windows上用batch来实现就需要一段代码,而且还不优美。

for循环中使用变量时的注意事项

# 注意下面2个for循环的不同之处
# 一个有 /f 选项,所有后面的括号里面有双引号
# 一个没有 /f 选项,后面没有 tokens 参数以及括号里面也没有双引号
for /f "tokens=1" %%a in ("%date:/=-%") do (set mydate=%%a)
for %%a in (%time::=%) do (set mytime=%%a)

# batch脚本中 %~dp0 和 %~n0 变量的取值
set tmpfile="%~dp0%~n0-%mydate%.txt"


# batch脚本中for循环使用 call 子例程的方式来更新变量的值(直接用的话值是固定的)
:: set variable ip
set ip=
ipconfig | findstr /i ipv | findstr 1[97]2 >%tmpfile%
for /f "tokens=2 delims=:" %%a in (%tmpfile%) do (
echo %%a
call :subroutine_ip %%a
)
:subroutine_ip
set ip=%1,%ip%
goto :eof

set ip=%ip:~0,-1%
echo %ip%
Windows上如何判断操作系统是32位的还是64位的?
# 操作系统的架构
wmic os get osarchitecture

# 处理器的架构
echo %PROCESSOR_ARCHITECTURE%
batch批处理脚本中如何判断某个变量是否为空值?
IF [%1] == [] GOTO MyLabel
:: or
IF "%~1" == "" GOTO MyLabel
batch批处理脚本中如何判断字符串是否不相等?
if NOT "asdf" == "fdas" echo asdf
batch批处理脚本中如何进行字符串截取?
语法:
%variable:~start_index%
%variable:~start_index,end_index%

:: 截取ip变量子串,去掉最后一个字符
set ip=%ip:~0,-1%
bat批处理中的注释语法
:: comments here
Rem comments here
bat批处理中如何做字符串替换
@echo off 
set str=This message needs changed. 
echo %str% 

set str=%str:needs=has% 
echo %str%
batch批处理脚本中如何获取当前的日期时间?
for /f "tokens=1" %%a in ("%date:/=-%") do (set mydate=%%a)

for %%a in (%time::=%) do (set mytime=%%a)
Windows下如何进行文件下载和HTTP请求操作
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://ixyzero.com/blog/awk_sed.txt', 'awk_sed.txt')"

powershell -Command "Invoke-WebRequest https://ixyzero.com/blog/awk_sed.txt -OutFile awk_sed.txt"

curl -o awk_sed.txt https://ixyzero.com/blog/awk_sed.txt
Windows的命令行下的文件操作
# 创建空文件
type nul > filename.txt
copy NUL EMptyFile.txt
copy /b NUL EmptyFile.txt
echo. 2>EmptyFile.txt
REM. > empty.file
fsutil file createnew file.cmd 0 # to create a file on a mapped drive

# 创建指定大小的文件
fsutil file createnew filename.txt 1000

# 打印文件内容,类似于Linux上的cat命令
type filename.txt

# 删除文件,类似于Linux上的rm命令
del filename.txt

# 查看当前目录下有哪些文件,类似于Linux上的ls命令
dir

# 创建目录
mkdir dir_name

# 删除目录
rmdir dir_name
Windows的命令行下的复制
# 无任何选项,仅复制文件,不复制目录
xcopy \path\to\source \path\to\dest

# 无任何选项,目标是一个还没创建的目录,需要交互式互动才可继续
xcopy \path\to\source \path\to\dest\none_exist_dir

# 借助管道将上面的命令从交互式改成静默执行的
echo d | xcopy \path\to\source \path\to\dest\none_exist_dir

# 添加 /e 选项,复制包括空目录在内的目录和子目录,但是如果有同名文件,则会需要交互以确定是否进行覆盖
xcopy /e \path\to\source \path\to\dest

# 添加 /e 和 /y 选项,直接复制包括空目录在内的目录和子目录,如果有同名文件,直接进行覆盖即可
xcopy /e /y \path\to\source \path\to\dest

# 简而言之,一个简单实用的xcopy命令就是——直接将源目录拷贝到一个之前不存在的目录下
echo d | xcopy /y /e \path\to\source \path\to\dest\none_exist_dir

xcopy /?
...
  /S           复制目录和子目录,不包括空目录。
[*]  /E           复制目录和子目录,包括空目录。与 /S /E 相同。可以用来修改 /T。
[*]  /C           即使有错误,也继续复制。
[*]  /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    如果适用,在传输期间请求网络压缩。
...
参考链接:

for循环中使用变量时的注意事项
https://ss64.com/nt/for.html

Windows上如何判断操作系统是32位的还是64位的?
https://superuser.com/questions/321988/how-do-i-determine-if-my-windows-is-32-bit-or-64-bit-using-a-command

batch批处理脚本中如何判断某个变量是否为空值?
https://stackoverflow.com/questions/2541767/what-is-the-proper-way-to-test-if-a-parameter-is-empty-in-a-batch-file

batch批处理脚本中如何判断字符串是否不相等?
https://stackoverflow.com/questions/1421441/batch-not-equal-inequality-operator
https://ss64.com/nt/if.html

batch批处理脚本中如何进行字符串截取?
https://stackoverflow.com/questions/636381/what-is-the-best-way-to-do-a-substring-in-a-batch-file
https://ss64.com/nt/syntax-substring.html

Batch Script – Comments
https://www.tutorialspoint.com/batch_script/batch_script_comments.htm

How to “comment-out” (add comment) in a batch/cmd?
https://stackoverflow.com/questions/11269338/how-to-comment-out-add-comment-in-a-batch-cmd

Batch Script – Replace a String
https://www.tutorialspoint.com/batch_script/batch_script_replace_string.htm

How to replace substrings in windows batch file
https://stackoverflow.com/questions/5273937/how-to-replace-substrings-in-windows-batch-file/5274061#5274061

batch批处理脚本中如何获取当前的日期时间?
https://stackoverflow.com/questions/203090/how-do-i-get-current-date-time-on-the-windows-command-line-in-a-suitable-format

CURL was added to Windows 10 (1903) from build 17063 or later.
https://ss64.com/nt/curl.html

Windows batch file file download from a URL
https://stackoverflow.com/questions/4619088/windows-batch-file-file-download-from-a-url

Windows的命令行下的文件操作
https://stackoverflow.com/questions/1702762/how-can-i-create-an-empty-file-at-the-command-line-in-windows

Windows的命令行下的复制
https://ss64.com/nt/xcopy.html

=END=


《“Windows批处理脚本编写学习”》 有 2 条评论

  1. 如何从命令行获取Windows的系统版本号?
    How to get the ACTUAL version number for Windows 10 from command line? (NOT build number!)
    https://superuser.com/questions/1519110/how-to-get-the-actual-version-number-for-windows-10-from-command-line-not-buil
    `
    >Reg Query “HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion” | findstr ReleaseId

    >powershell -Command “(Get-ItemProperty -Path ‘HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion’).ReleaseId”

    >powershell -Command “Get-ComputerInfo -Property WindowsVersion”

    >winver

    >wmic os get /?

    >wmic os get version /value
    Version=10.0.19041

    >wmic os get buildnumber /value
    BuildNumber=19041
    `

  2. 软件下发任务
    `
    1. 获取主机相关信息
    2. 判断X软件是否正在运行(根据运行中进程或是特定路径的文件)
    3. 若正在运行,再判断安装运行的版本,若版本太低就下载升级安装,若版本已是最新则只进行 curl 请求上报主机相关信息用于标记和记录,然后退出
    4. 若没有运行,则下载并执行安装包,然后等一会发送 curl 请求用于记录下载安装情况,再退出

    host/ip/sn/os/agent_proc_list

    涉及到的命令主要就是:
    hostname/ipconfig/wmic/tasklist/findstr/dir/start/curl/powershell/…
    `

abc进行回复 取消回复

您的电子邮箱地址不会被公开。