我为家用计算机制作了此脚本,以将所有照片和视频轻松备份到一个外部硬盘驱动器上。
SET BackUpDir=%~d0\BackUpDir
for %%d in (C:\ D:\) do (
if exist %%d (
robocopy %%d %BackUpDir% *.jpg *.jpeg *.dng *.nef *.mp4 *.mov *.wmv *.avi *.3gp *.3g2 /MIN:20000 /MAX:2703622144 /s /W:15 /XD C:\$WINDOWS.~BT "C:\System Volume Information" C:\Windows "C:\Program Files" C:\Boot C:\MSOCache C:\Recovery "C:\Program Files (x86)" "C:\Documents and Settings" C:\ProgramData "C:\Users\All Users" C:\Users\Default "C:\Users\Default User" C:\Users\defaultuser0 C:\Users\Public )
)
exit 0
我有几台具有不同分区结构的计算机。其中一个仅具有驱动器C:
和D:
,但是例如第二个具有五个分区。
现在我有了这行代码,仅在两个分区上查找文件:
for %%d in (C:\ D:\) do (
我不想每次都编辑脚本来添加其他分区,例如在第一台计算机上不存在,但在第二台计算机上确实存在。我希望我的脚本自动查找计算机上所有可用的分区,但要执行备份脚本的外部硬盘驱动器除外。
如何更改上面的命令行以实现此目的?
我想要这样的东西:
for %%d in ("list of all partition" except "backup external hard drive") do (
答案 0 :(得分:1)
您已经知道如何获取要排除的驱动器,它位于第一行%~d0
中,因为您正在使用它来设置要备份的目录。直到。
此外,您可以使用exist
来找出实际存在的驱动器。
因此以下脚本将处理所有存在的驱动器,这些驱动器与运行脚本的驱动器不匹配:
@echo off
rem Expand following list as needed.
for %%d in (C D E F G H I J) do (
if exist %%d:\. if not %%d:==%~d0 (
echo Processing drive %%d
)
)
当我从具有C:
驱动器,空的C:
DVD和D:
SSD的系统上的驱动器E:
运行该驱动器时,我得到: / p>
Processing drive E
答案 1 :(得分:1)
我建议使用此代码:
@echo off
set "BackUpDir=%~d0\BackUpDir"
for /F "skip=1" %%I in ('%SystemRoot%\System32\wbem\wmic.exe LOGICALDISK where DriveType^=3 GET DeviceID') do (
if /I not "%~d0" == "%%I" %SystemRoot%\System32\robocopy.exe %%I\ %BackUpDir% *.jpg *.jpeg *.dng *.nef *.mp4 *.mov *.wmv *.avi *.3gp *.3g2 /MIN:20000 /MAX:2703622144 /s /W:15 /XD C:\$WINDOWS.~BT "C:\System Volume Information" C:\Windows "C:\Program Files" C:\Boot C:\MSOCache C:\Recovery "C:\Program Files (x86)" "C:\Documents and Settings" C:\ProgramData "C:\Users\All Users" C:\Users\Default "C:\Users\Default User" C:\Users\defaultuser0 C:\Users\Public
)
Windows管理规范命令 WMIC 用于访问Win32_LogicalDisk class的信息。感兴趣的数据是驱动器号,其中冒号存储在属性DeviceID
中。
当前连接的所有逻辑磁盘将通过命令行输出:
%SystemRoot%\System32\wbem\wmic.exe LOGICALDISK GET DeviceID
输出例如:
DeviceID
C:
D:
E:
F:
Q:
R:
S:
每行逻辑磁盘都有一个带有DeviceID
的标题行和下一行。所有行都有尾随空格。输出文本为UTF-16 Little Endian(每个字符两个字节),而不是ANSI(每个字符一个字节)编码。
但是对于备份任务而言,有趣的是只有本地磁盘。因此,命令行被修改为:
%SystemRoot%\System32\wbem\wmic.exe LOGICALDISK GET DeviceID,DriveType
例如,带有尾部空格的Unicode编码输出现在为:
DeviceID DriveType
C: 3
D: 3
E: 3
F: 3
Q: 5
R: 5
S: 2
好的,驱动器号与驱动器类型信息一起输出。根据 Win32_LogicalDisk 类的Microsoft文档,备份操作需要使用3
类型的驱动器。
使用 IF 条件可以过滤 FOR 循环中的行。但是wmic.exe
也提供了使用where
进行过滤的可能性。因此,可以使用命令行通过wmic.exe
直接过滤驱动器列表:
%SystemRoot%\System32\wbem\wmic.exe LOGICALDISK where DriveType=3 GET DeviceID
带有尾部空格的UTF-16 LE编码输出例如:
DeviceID
C:
D:
E:
F:
这是要通过 FOR 循环处理的输出,就像上面的批处理文件代码一样。
在这种情况下,带有选项/F
的 FOR 在后台以%ComSpec% /c
和圆括号内两个'
之间的命令行开始新的命令处理在执行过程中,将Windows安装到C:\Windows
中后的结果附加:
C:\Windows\System32\cmd.exe /c C:\Windows\System32\wbem\wmic.exe LOGICALDISK where DriveType=3 GET DeviceID
等号=
不是用双引号引起来的参数字符串的一部分。因此,cmd.exe
处理批处理文件将把字符=
解释为参数分隔符,例如空格,制表符或逗号,并在执行命令 FOR之前将=
替换为空格字符。因此,由在后台启动的单独命令进程执行的命令行将使用where DriveType 3
而不是where DriveType=3
,并且这对于where
子句来说是无效的语法。因此,在执行命令^将整个 FOR 命令行及其命令块解析为cmd.exe
时,必须使用cmd.exe
来将等号转义为文字字符> FOR 。
FOR 捕获所有输出以处理已启动命令过程的 STDOUT ,并在启动I
自身终止后逐行处理捕获的文本。
FOR 在处理捕获的输出时始终忽略空行。
FOR 默认情况下使用普通空格和水平制表符作为分隔符将每一行拆分为子字符串,并仅将第一个空格/制表符分隔的字符串分配给指定的循环变量eol=;
。这正是此处所需的行处理行为。
FOR 默认情况下也会忽略所有以分号开头的行,因为;
是行尾选项的默认选项。行尾选项此处不得更改,因为要处理的所有行均以驱动器号开头。
在实际的 FOR 中,首先使用指定的或默认的字符串定界符分隔行,然后检查第一个子字符串是否以指定的或默认的行尾字符开头。因此, FOR 在这种情况下也将忽略以例如一个或多个前导空格/制表符开头且下一个字符为DeviceID
的行。但这不会在此处发生,因此可以保留 FOR 的默认行尾选项。
但是第一条带有skip=1
的输出行就没有意义了。在 FOR 中,通过使用"
中包含的选项if /I not "%~d0" == "%%I"
,可以跳过此行。
在备份驱动器是驱动器类型为2
的可移动磁盘时,很有可能没有必要附加条件protected fun verifyToastMessageWithText(text: String, activityTestRule: ActivityTestRule<*>) {
onView(withText(text)).inRoot(withDecorView(not(activityTestRule.activity.window.decorView))).check(matches(isDisplayed()))
}
protected fun verifyToastMessageWithStringResource(id: Int, activityTestRule: ActivityTestRule<*>) {
onView(withText(id)).inRoot(withDecorView(not(activityTestRule.activity.window.decorView))).check(matches(isDisplayed()))
}
。但是,也可以使用此代码将除备份驱动器以外的所有本地驱动器备份到也是本地驱动器的备份驱动器上。