无忧启动论坛

标题: (2018.03.13)挂载 卸载分区 盘符的 diskpart 脚本 [打印本页]

作者: dos时代菜鸟    时间: 2018-3-10 21:19
标题: (2018.03.13)挂载 卸载分区 盘符的 diskpart 脚本
本帖最后由 dos时代菜鸟 于 2018-3-13 10:38 编辑

增加点儿人气,呵呵,只贴源码,不贴文件,方便讨论,方便更新,不必上传。,需要的,自己复制粘贴成脚本吧。

还是贴个文件,不然不知道 需求量, L-D_drv6.2.cmd.zip (1.68 KB, 下载次数: 129)


脚本小,却有很多思考。
比如
remove 的 dismount 参数的 特点
如何 获取 某文件 某行,第一个单词 和 该行 地n个字符
如何分析 提取 混乱 文本中 特定特点 的 某行内容
如果 用 文本中 上一行的内容 做标记 来 确定本行是 所要数据行
cmd脚本中  程序段 call :lable 的使用 和 Exit /b 的使用
考虑英文环境的存在,搜索特定行 用的关键字 不能是中文,

  1. @echo off
  2. setlocal ENABLEDELAYEDEXPANSION
  3. COLOR 0A
  4. mode con: lines=40 cols=120
  5. title 挂/卸载分区
  6. :确定硬盘序列,并生成 罗列分区信息
  7. :top1
  8. echo 正在探测数据........
  9.   >%temp%\disk_load.txt echo list vol
  10.   >%temp%\dl.txt diskpart /s %temp%\disk_load.txt
  11.   call :fresh
  12. :top2
  13.   cls
  14.   echo  Diskpart 挂/卸载分区 Diskpart_Ver:%ver%
  15.   echo --------------------------------------------------------------------------------------------
  16.   echo   Vol  盘符 标签           FS      类型        大小         状态       信息   
  17.   echo  ---- ----- -----------  -----  ------------  ---------  ---------  --------
  18.   set m=-1
  19.   for /f "tokens=*" %%o in (%temp%\part_list.txt) do ( ECHO   %%o  & set /a m=!m!+1)
  20.   echo --------------------------------------------------------------------------------------------
  21.   set n=-1
  22.   set /p n=请输入待处理卷对应的卷号(Vol):0-!m!,r刷新,x退出:
  23.   if /i "!n!"=="x" goto x
  24.   if /i "!n!"=="r" goto top1
  25.     echo --------------------------------------------------------------------------------------------
  26.     call :drv_x  &        if errorlevel 9 goto top2
  27.     call :L      &        if errorlevel 9 goto top2
  28.     echo ------------------------------------------
  29.     call :script
  30.   ))
  31. goto top2

  32. :分配盘符
  33. :L
  34.   set d=!drvs:~0,1!
  35.   set /p d=请输入一个新盘符,!drvs!默认!drvs:~0,1!,0卸载,9返回,回车确认:
  36.   if "!d!"=="9"  exit /b 9
  37.   if "!d!"=="0"  goto l2
  38.   :l1
  39.     set f=0
  40.     for %%c in (%drvs%) do (if /i "%%c"=="!d!" set f=1)
  41.     if !f!==0  (echo 输入错误,按任意键重新来过... & pause>nul & exit /b 9)
  42.     >>%temp%\disk_load.txt echo assign letter=!d!
  43.     goto l_ok
  44.   :l2
  45.       if not "!dm!"=="" ( if  "!drv!"==" " ( >>%temp%\disk_load.txt echo assign) )
  46.       >>%temp%\disk_load.txt echo remove !dm! noerr
  47.   :l_ok
  48.       >>%temp%\disk_load.txt echo list vol
  49.   echo 正在生载脚本...
  50. exit /b 1

  51. :运行脚本
  52. :script
  53. echo Script (disk_!dx!:!px!):
  54. echo ------------------------------------------
  55. type %temp%\disk_load.txt
  56. echo ------------------------------------------
  57. echo 按任意键开始处理.........
  58. pause>nul
  59. echo 正在运行脚本并刷新数据......
  60. >%temp%\dl.txt diskpart /s %temp%\disk_load.txt
  61. call :fresh
  62. exit /b 1

  63. :检验选取分区是否正确,并生成diskpart基本脚本
  64. :drv_x
  65.   echo 正在验证所选^(!n!^),探测对应分区................
  66.   set select=
  67.   for /f "tokens=*" %%c in (%temp%\part_list.txt) do (
  68.     set drv=%%c
  69.     set drv=!drv:~6,1!
  70.     for /f "tokens=1,*" %%d in ("%%c") do (set q=%%d)
  71.     if "!n!"=="!q!" (rem 生成卸载脚本
  72.         set select=ok
  73.          >%temp%\dx.txt echo select vol !n!
  74.         >>%temp%\dx.txt echo list disk
  75.         >>%temp%\dx.txt echo list partition        
  76.         set dx=
  77.         set px=
  78.         for /f "tokens=1,2,3,*" %%c in ('diskpart /s %temp%\dx.txt') do (
  79.             if "%%c"=="*" (if "!dx!"=="" set dx=%%e)
  80.             if "%%c"=="*" (if not "!dx!"=="" set px=%%e )
  81.         )
  82.         if not "!dx!"=="" (if not "!px!"=="" (
  83.            >%temp%\disk_load.txt echo select disk !dx!
  84.           >>%temp%\disk_load.txt echo select partition !px!
  85.         )) else (
  86.           echo 无法确定所选卷^(!n!^)对应的硬盘和分区,将直接处理卷.......
  87.            >%temp%\disk_load.txt echo select vol !n!
  88.         )
  89.     exit /b        0
  90.     )
  91. )
  92.   if not "!select!"=="ok" (
  93.     echo 选择错误,按任意键重新选择.....
  94.     pause>nul
  95.   )
  96. exit /b 9

  97. :fresh
  98.   rem 分析 diskpart 脚本运行结果(dl.txt)----整理出硬盘分区序列(part_list.txt)
  99.   >%temp%\part_list.txt echo.
  100.   set t0=
  101.   for /f "tokens=1,*" %%c in (%temp%\dl.txt) do (
  102.     set l0=%%c
  103.     if "%%c"=="Microsoft" (for /f "tokens=3" %%e in ("%%d") do (set ver=%%e))
  104.     if "!l0:~0,1!"=="-" set "t0=ok"
  105.     if "!t0!"=="ok" (if not "!l0:~0,1!"=="-" (
  106.       if "%%c"=="*" (for /f "tokens=1,*" %%r in ("%%d") do (echo %%s>>%temp%\part_list.txt )
  107.       ) else (echo %%d>>%temp%\part_list.txt )
  108.     ))
  109.   )
  110.   set dm=dismount
  111.   for /f "delims=. tokens=1" %%x in ("!ver!") do (if %%x lss 6 set dm=)
  112.   call :drv_z
  113. exit /b  

  114. :计算出可用盘符
  115. :drv_z
  116.   set drvs=
  117.   for %%x in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) DO (
  118.     SET F=0
  119.     for /f "tokens=2" %%c in (%temp%\part_list.txt) do (IF /i "%%x"=="%%c" set F=1)
  120.     if "!f!"=="0"  set drvs=%%x,!drvs!
  121.   )
  122.   echo 可用盘符:!drvs!
  123.   exit /b

  124. :结束
  125. :x
复制代码







作者: dos时代菜鸟    时间: 2018-3-10 21:24
本帖最后由 dos时代菜鸟 于 2018-3-10 21:32 编辑

多次调用 diskpart 获取分区 对应的 全部 硬盘及其分区 对应的 数字 和 磁盘分区状况,对所有分区 分配序号,供选择。
当分配 盘符的时候,如果用户输入的 盘符已经在序列内,就提示 重来。


因为要  cmd.exe 与 diskpart 间进行数据 变量的 交流,所以要在 cmd 中调用多次 diskpart.探测硬盘分区数据的时候可能会慢一些。

作者: 邪恶海盗    时间: 2018-3-10 22:04
强势插入,广告位出租...
作者: freesoft00    时间: 2018-3-10 22:10
最近很活跃呀。
作者: l3429900    时间: 2018-3-10 23:42
谢谢大神,分享有益,学习做一下
作者: dos时代菜鸟    时间: 2018-3-10 23:52
又更新

更新 循环,操作完一个 分区,刷新 磁盘序列 信息,继续 处理另一个分区。
考虑到  获取 磁盘序列信息 时间比较长,所以 增加了一段代码, 在处理完一个分区以后,不必对 全部硬盘分区序列重新 读取,只要确认 更被操作的 那个分区的信息,并将信息更新到 序列列表。

作者: dos时代菜鸟    时间: 2018-3-10 23:54
freesoft00 发表于 2018-3-10 22:10
最近很活跃呀。

呵呵,编编 脚本,活跃下气氛而已。
很久没有 发帖,感觉 老了。
作者: dos时代菜鸟    时间: 2018-3-10 23:59
这个脚本 只对应 分区,如果 是那些 系统沉於的 “无主儿” 盘符 可就无法卸掉了。

作者: nttwqz    时间: 2018-3-11 00:11
dos时代菜鸟 发表于 2018-3-10 21:24
多次调用 diskpart 获取分区 对应的 全部 硬盘及其分区 对应的 数字 和 磁盘分区状况,对所有分区 分配序号 ...

的确,多次调用diskpart会延长命令执行时间,也不知道有没有什么办法解决。

话说,你这是写着玩的吧,要不然有简单的方法。


  1. @echo off
  2. mode con cols=90
  3. set /p=list vol<nul | diskpart
  4. echo 选择要卸载的卷:
  5. set /p vol=
  6. (echo sel vol %vol% & echo remove) | diskpart
  7. pause
复制代码

作者: freesoft00    时间: 2018-3-11 00:43
dos时代菜鸟 发表于 2018-3-10 23:54
呵呵,编编 脚本,活跃下气氛而已。
很久没有 发帖,感觉 老了。

支持。
用dos的大部分岁数都有些了。
作者: dos时代菜鸟    时间: 2018-3-11 08:20
nttwqz 发表于 2018-3-11 00:11
的确,多次调用diskpart会延长命令执行时间,也不知道有没有什么办法解决。

话说,你这是写着玩的吧, ...

其实 挂载也有简单的方法,需要变通一下,用 mountvol 挂载到 目录里面,用完直接删除挂载目录
  1. @echo off && setlocal ENABLEDELAYEDEXPANSION
  2. pushd "%~dp0"
  3. cd /d "%~dp0"
  4. set "p0=%~dp0"
  5. if not ""=="%~1" set "p0=%~1"
  6. if not "!p0:~-1,1!"=="" set p0=!p0!\
  7. ECHO 联接目录:!P0!
  8. set n=0
  9. for /f "tokens=1 delims= " %%i in ('mountvol /l') do (
  10. set "p=%%i"
  11. if "!p:~1,1!"=="" set "p1=%%i"
  12. if "%%i"=="***" (
  13.         ECHO 待联接卷:!P1!
  14.         set "p=!p0!!p1:~12,35!"
  15.         if exist "!p!" rd /q "!p!"
  16.         mklink /d "!p!" "!p1!">nul
  17.         if not !errorlevel! EQU 1 set /a n=!n!+1
  18. )
  19. )
  20. echo 共有 !n! 个卷联接到了 "!p0!"
  21. if !n! gtr 0 (
  22.         echo 按任意键将浏览  "!p0!" ...&&pause>nul
  23.         start explorer.exe "!p0!"
  24. ) else (
  25.         pause
  26. )
  27. for %%c in (p0 p p1 n) do set %%c=
复制代码

作者: dos时代菜鸟    时间: 2018-3-11 09:04
把 装卸 合于一个了,看一楼
作者: dos时代菜鸟    时间: 2018-3-11 10:38
xp 的 diskpart 的remove没有 dismount 参数,所以只能用在win7。
作者: freesoft00    时间: 2018-3-11 14:03
dos时代菜鸟 发表于 2018-3-11 10:38
xp 的 diskpart 的remove没有 dismount 参数,所以只能用在win7。

xp就被考虑了。xp的diskpart命令比较弱,有些参数不支持。

磁盘分区命令,想xp也能用。可以考虑使用win版的gdisk,赛门铁克那个,这个老兄应该驾轻就熟。现在纯dos逐渐的在没落,维护进pe的机会越来越多。
作者: dos时代菜鸟    时间: 2018-3-11 15:22
本帖最后由 dos时代菜鸟 于 2018-3-11 15:30 编辑

再次改进,发现 list parttion , detail partiton的方式 不能发现 u盘。
信息搜集 用 list vol
但是发现在
select vol 以后,用 remove 命令有局限,这个 dismount 参数 就有不好用的情况,不能让磁盘分区脱机,所以 还是要用到 select partiton
这就需要 确定 partition 对应的数字,所以 后面 对 某个分区的 装卸 可能要慢一些,但是 脚本运行初期,数据的收集 就 快了。

另外增加了 判断 diskpart 版本 小于 6 的时候,不使用 dismount 参数。

使用 remove 附带 dismount 参数 目的就是可以 直接 卸掉 u盘,然后 u盘就可以拔出了。

具体脚本更新,在一楼。
作者: dos时代菜鸟    时间: 2018-3-11 22:03
闲着 也是 闲着
继续改进
增加一个  计算出 空闲盘符 的 段子,放进去了。挂载 分区 输入盘符的时候 ,进行判断 会更准确。
作者: rengrancunzai    时间: 2018-3-12 08:29
谢谢分享
作者: devilma    时间: 2018-3-12 16:31
谢谢分享!收藏!
作者: dos时代菜鸟    时间: 2018-3-13 09:33
研究改进之:
改进 版本判断方法,否则 10 的 版本会被判定为 1
发现 remove 的 dismount 参数只对  有盘符的 分区起作用,改进 就是先 随便分配个盘符,在 卸载。
增加对  不能识别硬盘分区的卷 ,比如 光驱,进行处理
不必选择 挂/卸,当要求输入 盘符的时候,如果输入的 是 "0" ,就卸载之。


作者: dos时代菜鸟    时间: 2018-3-13 09:52
本帖最后由 dos时代菜鸟 于 2018-3-13 11:53 编辑

还是有问题
那个  assign 对于 efi 分区 可以无限次的 分配盘符,就会导致 多个盘符指向一个分区。卸载的时候 就失效了。
看来还要 调整一下,价格判断。

已经改进 ,判断卷是否被分配了盘符


脚本小,却有很多思考。
比如
remove 的 dismount 参数的 特点,
                只有 当 确定版本 大于 6.x 包含 dismount 参数,并且 目标卷 已经分配盘符 的情况,用 dismount 才会 使 该卷 脱机,如果是u盘 ,此时就可以拔掉了。
                dismount 对于隐藏分区 也是 失效的。比如 efi 分区。
如何 获取 某文件 某行,第一个单词 和 该行 地n个字符
  1. for /f "tokens=*" %%c in (x.txt)
  2.           set l=%%c
  3.           echo 第六个字符:%l:~5,1%
  4.           for /f "tokens=1" %%d in ("%%c") do (
  5.                 echo 第一个单词:%%d
  6.           )
  7. )
复制代码
如何分析 提取 混乱 文本中 特定特点 的 某行内容
如何 用 文本中 上一行的内容 做标记 来 确定本行是 所要数据行
cmd脚本中  程序段 call :lable 的使用 和 Exit /b 的使用
考虑英文环境的存在,搜索特定行 用的关键字 不能是中文,


再有问题在改进
作者: dos时代菜鸟    时间: 2018-3-13 14:39
diskpart 对 u 盘
select partition 有大部分情况是失效的。但是 detail disk 这个 盘,发现u盘的 partition 已经是焦点了。真是  无语 。
作者: lc1212    时间: 2018-4-20 17:45
感谢分享,收下备用了。
作者: liguibin    时间: 2018-7-7 14:00
谢大神,分享有益




欢迎光临 无忧启动论坛 (http://bbs.wuyou.net/) Powered by Discuz! X3.3