zoukankan      html  css  js  c++  java
  • bat 与 PowerShell 的结合使用


    前言

    背景: 前前段时间,做文件操作处理时,有这么一个场景: window 下需要对某固定目录下的文件及其他文件进行拷贝操作, 至目标对象---> 外置存储设备(U盘或移动硬盘),且需要一定大小的存储量并做判断提示。
    问题: 其主要问题不在文件拷贝操作,而是对外置存储设备的处理(主要是对磁盘大小的判断,也就是数字的比较及计算)。首先批处理的数字处理有一定范围(正负 2^31-1),其次超出范围的比较情况还有不同。
    解决: 其一则是正面刚(截取操作再比较),其二则是绕过换其他方法(调 PowerShell 处理)

    一、使用 bat 做数字比较

    1.下图为批处理数字比较的情况:两个值都超出范围的比较,结果相反

    2.以下为当时的脚本(后面磁盘大小的计算实在不知道咋怎,用了 PowerShell ):

    @echo off & setlocal enabledelayedexpansion
    rem =========================================================
    rem ==  The tools develop for copy files to external disk  ==
    rem	==			author: by zzw							   ==
    rem ==			datetime: 2019.07.1                        ==
    rem =========================================================
    
    @rem chcp 936 ::更换默认编码
    
    @rem 源路径
    set srcPath=F:zzwTest
    
    @rem 本地磁盘驱动器: C: D: E:
    :HasDrive
    for /f "tokens=1,* delims= " %%i in ('fsutil fsinfo drives') do (
    	set d=%%j
    	set d=!d:=!
    	@rem echo !d!. 遍历磁盘信息是否包含 移动 字符
    	for %%a in (!d!) do (
    		fsutil fsinfo driveType %%a | findstr "移动" >nul && set driver=%%a
    	)
    	
    	@rem 移动硬盘会被指定为固定驱动器.需要去除本地磁盘
    	if not defined driver (
    		set d=!d:C:=!
    		set d=!d:D:=!
    		set d=!d:E:=!
    		set d=!d: =!
    		set driver=!d!
    		if "!d!"=="" ( call :Tip1 ) else ( call :Tip1 ZZW )
    	)
    	goto DriverSpace
    )
    
    :DriverSpace
    if defined driver (
    	@rem 包含 可用字节总数 的行,取第一行
    	for /f "tokens=1,2 delims=:" %%i in ('fsutil volume diskFree %driver% ^|findstr "可用字节总数"') do (
    		set free=%%j
    		@rem echo !free! | findstr "(" && set free=!free:*(=! & set free=!free:^)=! || set free=!free: =!
    		for /f "tokens=1 delims= " %%x in ("!free!") do (
    			set free=%%x
    		)
    		@rem calculate disk size. multiplier of 1.1
    		@rem debug: set free=1048576000
    		if !free! LSS 1126 ( call :Tip3 1 B )
    		if !free! LSS 1153433 ( call :Tip3 1024 KB )
    		if !free! LSS 1181116006 ( call :Tip3 1024*1024 MB )
    		call :Tip3 1024*1024*1024 GB
    		
    		:Below
    		@rem 批处理数值范围在正负 2^31-1 = 2147483647
    		set total=!free!t
    		if "!total:~10!"=="" (
    			@rem echo 小于 10 位数 0.93GB=999999999B  0.5GB=536870912B
    			if "!total:~8!"=="" ( call :Tip2 [10MB] ★★★警告★★★)
    			if "!total:~9!"=="" ( call :Tip2 [100MB] ★★★警告★★★)
    			set totalN=!total:~0,9!
    			if !totalN! LSS 104857600 ( call :Tip2 [100MB] ★★★警告★★★)
    			if !totalN! LSS 262144000 ( call :Tip2 [250MB] ★★★警告★★★)
    			if !totalN! LSS 536870910 ( call :Tip2 [500MB] ★★★警告★★★)
    			call :Tip2 [1GB]
    		)
    		if "!total:~10!"=="t" ( 
    			@rem echo 等于 10 位数 6GB=6442450944B
    			set totalA=!total:~0,10!
    			if !totalA! LSS 1048576000 ( call :Tip2 [1GB] )
    			if !totalA! LSS 1610612735 ( call :Tip2 [1.5GB] )
    			if !totalA! LSS 2147483646 ( call :Tip2 [2GB] )
    			set totalB=!total:~0,9!
    			if !totalB! LSS 268435456 ( call :Tip2 [2.5GB] )
    			if !totalB! LSS 322122547 ( call :Tip2 [3GB] )
    			if !totalB! LSS 429496729 ( call :Tip2 [4GB] )
    			if !totalB! LSS 536870912 ( call :Tip2 [5GB] )
    			if !totalB! LSS 644245094 ( call :Tip2 [6GB] )
    		)
    		goto ReSelect
    	)
    )
    
    :Tip1
    color 0b & echo, 
    echo 	请确保外置 [U盘] 或 [移动硬盘] 插入成功!!!& echo,
    if not "%1"=="" ( echo 	磁盘识别错误,请联系开发者 ----^> %1& echo, )
    goto End
    
    :Tip2
    color 0b & echo, 
    echo 	请确保 %driver% 盘空间至少 6GB 可用 & echo,
    if not "%2"=="" echo 	%2
    echo 	注意 %driver% 盘空间小于 %1 ,不建议继续操作,默认 N 
    echo 	若继续将可能导致部分文件复制失败!!!
    echo,
    set /p confirm=请确认是否要继续(N/Y)_^>^>
    if /i %confirm%==y goto ReSelect
    goto End
    
    :Tip3
    set /p =◆ %driver% 磁盘可用空间(约)为: <nul
    @rem powershell -c "[String]$i=!free!/(%1);if($i.contains('.')) {$s=$i.split('.'); $s[0],$s[1].substring(0,3)+'%2' -join('.')} else {$i+'%2'}"
    powershell -c "[String]$i=!free!/(%1);if($i.contains('.')) {$s=$i.split('.'); $s[0]+'.'+$s[1].substring(0,3)+' %2'} else {$i+'%2'}"
    goto Below
    
    :ReSelect
    color 0a
    echo,
    echo *********该工具将拷贝所选目录文件至 %driver% 盘设备********
    echo,
    echo 	请在下列选项中选择需要操作的路径(如: 1 、2 、3 )
    echo,
    echo ==========================================================
    set a=0
    for /f %%i in ('dir /b /ad "%srcPath%"') do (
    	set /a a+=1
    	echo 	[!a!] %%i
    )
    echo,
    echo ==========================================================
    set a=0
    set /p number=请输入:
    for /f %%i in ('dir /b /ad "%srcPath%"') do (
    	set /a a+=1
    	if !a!==%number% set testResult=%%i & echo, & echo 你的选择是 %%i
    )
    if not defined testResult (
    	color 04
    	echo,
    	echo 请选择正确的选项!
    	echo 请按任意键重新选择!
    	pause >nul & cls & goto ReSelect
    )
    echo,
    
    echo "=====可以开始操作了======"
    
    :End
    pause
    

    从以上脚本看来,在 cmd 中使用大的数据比较时非常吃力,脚本还一坨一坨的。而 PowerShell 则简单了,请看下列分析及操作操作。

    二、CMD 命令行 PowerShell 的使用

    在使用前首先来介绍下:
    Windows PowerShell 是一种命令行外壳程序和脚本环境,使命令行用户和脚本编写者可以利用 .NET Framework的强大功能 ----->百度百科

    1.在cmd 命令行中 powershell /? 先查看简要帮助文档(以下为比较关注信息),这里顺便贴上官方路径

    2.若要运行PowerShell 脚本或者命令,可能需要使用 PowerShell 需要开启相关权限,如下操作即可:

    @echo off
    
    @rem set the execution mode of the PowerShell
    set flag=1
    @rem -c 等同 -Command
    powershell -c "Get-ExecutionPolicy" |findstr "Restricted" >nul && set flag=0
    if %flag% == 0 ( 
            :: powershell -ExecutionPolicy RemoteSigned  与下句等同
    	powershell -c "Set-ExecutionPolicy RemoteSigned" 
    	echo Allowed to use powershell
    )
    
    

    3.着重实践下重点关注的地方

    PowerShell[.exe] [-PSConsoleFile <file> | -Version <version>]
        [-NoLogo] [-NoExit] [-Sta] [-NoProfile] [-NonInteractive]
        [-InputFormat {Text | XML}] [-OutputFormat {Text | XML}]
        [-WindowStyle <style>] [-EncodedCommand <Base64EncodedCommand>]
        [-File <filePath> <args>] [-ExecutionPolicy <ExecutionPolicy>]
        [-Command { - | <script-block> [-args <arg-array>]
                      | <string> [<CommandParameters>] } ]
    
    
    #  Command 的值为"-", 将会打印帮助文档 同 powershell -c
    powershell -c -
    
    # Command 的值为脚本块,只在 powershell 环境下才有效。
    # 而 cmd 下会原样输出,且数据必须在括号中,否则报错
    powershell -c {Test $HOME}
    
    # Command 的值为字符串,则该字符串必须是最后一个参数
    # 执行字符串中的命令返回结果且输出 test
    powershell -c "echo $HOME" test   
    
    # 运行 Windows PowerShell 命令的字符串, 不会输出 test
    powershell -c "& {$HOME}" test
    
    # 实际发现省略 -c 命令也可以实现(暂未深入研究其原因)
    powershell $HOME
    
    

    结果如图:

    三、使用 PowerShell 做数字比较

    1.通过上述的帮助文档,就可以愉快的做数字比较和计算了。不过这里还是列一下 PowerShell 的比较运算符,其他还是移步官方文档或文末链接地址查阅。

    -eq:等于            -ne:不等于
    -gt:大于             -ge:大于等于
    -lt:小于             -le:小于等于
    -contains:包含        -notcontains:不包含
    

    2.再来看看数字比较和计算,可以发现很方便,既能通过判断自定义显示结果,也能直接显示比较结果。

    3.对于最开始的磁盘空间比较计算的问题已经可解决了,但大串的数字写起来还是挺麻烦的,不过 PowerShell 可以识别计算机容量单位, 包括 KB,MB,GB,TB,PB。那么我们就能更加愉快的玩耍了

    @echo off
    for /f "tokens=1,2 delims=:" %%i in ('fsutil volume diskFree D: ^|findstr "可用字节总数"') do (
    	@rem 计算时会进行四舍五入
    	@rem 等同 powershell "'{0:N2}' -f (%%j/1GB)"
    	powershell "$s='{0:0.00}' -f (%%j/1GB);$s+' GB'"
    )
    
    pause
    

    四、调用 PowerShell 的细节及场景

    1.调用本质
    整体来说在使用批处理时可以通过 PowerShell 来弥补不足。究其调用本质----> 开启一个 PowerShell 进程实现操作结束后退出。如图所示

    2.调用细节
    本文中的脚本只对调用 PowerShell 的结果进行展示,那如何赋值给变量或管道输出呢?

    # 不换行结果显示
    set /p =HomePath: <nul
    powershell "$HOME"
    
    # 输出值赋给批处理脚本变量
    for /f %%i in ('powershell "1+2"') do (
    	set sum=%%i
    )
    echo 赋值结果:%sum%
    
    # 管道输出给批处理的其他命令
    powershell $HOST | findstr /i name
    
    # 批处理参数传给 PowerShell 使用
    set total=100
    powershell "'平均值为: '+ %total%/10"
    
    

    3.其他场景

    批处理运行时弹框选项【powershell 弹框

    @echo off
    
    echo After 3 seconds, the prompt box will appear...
    timeout /t 3 >nul
    set pscommand='powershell "$IP=ForEach($ip in (ipconfig) -like '*IPv4*'){'IP Address:'+($ip -split ' : ')[-1]};$showIp=New-Object -ComObject WScript.Shell;$showIp.popup("$IP",0,'ShowIP',1+64)"'
    
    for /f %%i in (%pscommand%) do (
    	if %%i==1 ( echo You selected the OK button )
    	if %%i==2 ( echo You selected the CANCEL button )
    )
    
    pause
    

    批处理调用执行 PowerShell 脚本文件

    powershell -File .
    un.ps1
    

    未完,待续...

    PowerShell 博客

  • 相关阅读:
    SQL Server 阻止了对组件 'Ole Automation Procedures' 的 过程'sys.sp_OACreate' 的访问
    谷歌浏览器扩展程序manifest.json参数详解
    获取天气api
    UVA 10385 Duathlon
    UVA 10668 Expanding Rods
    UVALIVE 3891 The Teacher's Side of Math
    UVA 11149 Power of Matrix
    UVA 10655 Contemplation! Algebra
    UVA 11210 Chinese Mahjong
    UVA 11384 Help is needed for Dexter
  • 原文地址:https://www.cnblogs.com/zeo-to-one/p/11330156.html
Copyright © 2011-2022 走看看