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 博客

  • 相关阅读:
    哪有什么互联网寒冬?只是你穿的少而已!
    我不是机器人:谷歌最新版验证码系统ReCaptcha破解已开源
    Gradle更小、更快构建APP的奇淫技巧
    一篇文章让你了解Android各个版本的历程
    快速开发android,离不开这10个优秀的开源项目
    年底Android面试整理(附答案)
    最近Android真的凉凉了?
    Android 应用防止被二次打包指南
    开发了5年android,我开始了go学习之旅
    做了5年的Android,我转Java后台了!
  • 原文地址:https://www.cnblogs.com/zeo-to-one/p/11330156.html
Copyright © 2011-2022 走看看