剥离 CMD 输出以仅显示目录
Strip CMD output to just show directories
我目前正在尝试用 cmd 脚本替换 powershell 脚本,因为它更适合我正在尝试完成的工作。
在 Powershell 中,我使用这段代码 return 计算机上的个人文件夹目录列表
$Name = [Environment]::UserName
get-item HKCU:\software\Microsoft\Office.0\Outlook\Search\Catalog - ErrorAction SilentlyContinue | select -expandProperty property | Out-File Z:\global\pst\PowershellOutput$Name.txt -append
这就是我想要的,并输出一个目录列表,就像这样
H:\PST\My Outlook Data File 1.pst
H:\PST\My Outlook Data File 2.pst
C:\PST\My Outlook Data File 3.pst
但是当我运行这一行提取注册表项时
regedit.exe /e Z:\global\battest\%username%.txt "HKEY_CURRENT_USER\Software\Microsoft\Office.0\Outlook\Search\Catalog"
我得到一个包含大量不必要数据的输出
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Office.0\Outlook\Search\Catalog]
"H:\PST\My Outlook Data File 1.pst"=hex:0c,01,00,00,00,00,00,00
"H:\PST\My Outlook Data File 2.pst"=hex:f8,00,00,00,00,00,00,00
"C:\PST\My Outlook Data File 3.pst"=hex:ac,02,00,00,00,00,00,00
此数据被传递到另一个程序*,因此解决方法是使用“”标记内的数据,但它也有双反斜杠,这使得数据难以传递。
有没有更好的方法在 CMD 中获取这些值,或者我错过了一个只显示目录的参数?
- -很抱歉之前没有包括这个但是这个程序不是 CMD 程序,它是 visual basic
您可能需要使用 REG QUERY 命令。在单个 bat 文件中,它会像:
@echo OFF
for /f "usebackq tokens=1-3" %%A in (`REG QUERY "HKCU\Software\Microsoft\Office.0\Outlook\Search\Catalog"`) do (
set ValueName=%%A
)
echo %ValueName% > Z:\global\battest\%username%.txt
从 How can I get the value of a registry key from within a batch script?
得到这个
这是一个批处理代码,用于获取 *.pst 文件(不是目录)的列表,这些代码独立于 *.pst 文件的数量及其文件名,只要文件名以 .pst
.
结尾
@echo off
setlocal EnableExtensions EnableDelayedExpansion
for /F "skip=1 delims=" %%# in ('%SystemRoot%\System32\reg.exe query HKCU\Software\Microsoft\Office.0\Outlook\Search\Catalog 2^>nul') do (
set "RegData=%%#"
set "DelData=!RegData:*.pst=!"
if not "!DelData!" == "!RegData!" call :OutputFileName
)
endlocal
goto :EOF
:OutputFileName
set "RegData=!RegData:%DelData%=!"
echo !RegData:~4!
goto :EOF
*.pst 文件是 Outlook 个人存储文件,是电子邮件、联系人的容器文件,...
命令 FOR 运行控制台应用程序 REG 以查询注册表项的所有值:
HKEY_CURRENT_USER\Software\Microsoft\Office.0\Outlook\Search\Catalog
在 Windows Vista 和更新的 Windows 版本上的输出是为了示例:
HKEY_CURRENT_USER\Software\Microsoft\Office.0\Outlook\Search\Catalog
H:\PST\My Outlook Data File 1.pst REG_SZ whatever the
H:\PST\My Outlook Data File 2.pst REG_SZ data value is
C:\PST\My Outlook Data File 3.pst REG_SZ of each value
输出注册表项,然后是注册表值,每个注册表值缩进 4 个空格,值名称和值类型之间有 4 个空格,值类型和数据值之间有 4 个空格。
但在 Windows XP 上,输出为示例:
! REG.EXE VERSION 3.0
HKEY_CURRENT_USER\Software\Microsoft\Office.0\Outlook\Search\Catalog
H:\PST\My Outlook Data File 1.pst REG_SZ whatever the
H:\PST\My Outlook Data File 2.pst REG_SZ data value is
C:\PST\My Outlook Data File 3.pst REG_SZ of each value
因此在注册表项之前有前两行 header。注册表值也缩进了 4 个空格。但是值名称和值类型之间有 1 个或多个制表符而不是空格,并且值类型和数据值之间也有 1 个或多个制表符而不是空格。
注:不知道REG_SZ
是不是正确的注册表值类型。我的 Windows 注册表中根本没有此注册表项,因此只添加了 3 个注册表值作为带有虚拟字符串的字符串值。
所以棘手的部分是如何获取还包含空格的注册表值名称,以获取独立于文件名的 *.pst 文件的名称。
这是通过将每个输出行分配给环境变量 skip=1
的第一行除外,然后从该行获取下一个分配给环境的 .pst
之后的所有内容变量 DelData
.
如果该行在任何情况下都包含 .pst
导致 DelData
的值不等于 RegData
的值,则进一步调用子例程 OutputFileName
处理并打印 *.pst 文件的文件名。
在子例程 OutputFileName
中,首先使用字符串替换从 RegData
中删除 *.pst 文件名右侧的字符串。接下来输出*.pst文件名,开头没有4个缩进空格。
如果缩进空格数不总是恰好是 4 个空格,行 echo !RegData:~4!
可以替换为以下代码以独立于缩进数 spaces/tabs.
工作
for /F "tokens=1*" %%I in ("%RegData%") do (
if "%%J" == "" (
echo %%I
) else (
echo %%I %%J
)
)
使用 REG 而不是 REGEDIT 的优点是 运行 不需要提升管理员权限这个批号。
要了解使用的命令及其工作原理,请打开命令提示符 window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
call /?
echo /?
for /?
goto /?
reg /?
reg query /?
set /?
setlocal /?
如果注册表项不存在,则不输出任何内容。通过使用 2^>nul
将其重定向到设备 NUL,此处抑制了处理 STDERR 的错误消息输出。有关详细信息,请参阅 Microsoft 文章 Using command redirection operators。重定向运算符 >
必须在此处使用脱字符 ^
进行转义,以便在解析 FOR 命令行时被解释为文字字符,并在执行时被解释为重定向运算符REG 命令行的 FOR.
虽然我没有安装 Office 进行测试,但这应该可以完成工作
@echo off
setlocal enableextensions disabledelayedexpansion
set "HKCU=&H80000001"
set "subKey=software\Microsoft\Office.0\Outlook\Search\Catalog"
>> "Z:\global\pst\PowershellOutput\%username%.txt" (
for /f "tokens=2 delims={" %%a in ('
wmic
/NameSpace:\root\default
Class StdRegProv
Call EnumValues
hDefKey^="%HKCU%"
sSubKeyName^="%subkey%"
2^>nul
^| find "sNames = {"
') do for %%b in (%%a) do (
for /f delims^=^" %%c in ("%%~b") do echo(%%~fc
)
)
它使用 wmic
检索指定键下定义的值列表,并过滤输出以仅检索具有格式为 sNames = {"v1", "v2", "v3"}
.[=19 的这些值的名称的行=]
{
用于将行的开头与值列表 (%%a
) 分开,并迭代此列表 (%%b
) 以获取每个值。列表中的最后一个元素包含需要删除的结尾 }
,这由 %%c
使用值中的引号作为分隔符处理。
等效的 vbs 版本可以是
Option Explicit
Const HKEY_CURRENT_USER = &H80000001
Const ForAppending = 8
Const SUB_KEY = "software\Microsoft\Office.0\Outlook\Search\Catalog"
Const OUTPUT_PATH = "Z:\global\pst\PowershellOutput"
Dim fso, shell
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Set shell = WScript.CreateObject("WScript.Shell")
Dim values
Call GetObject( _
"winmgmts:{impersonationLevel=impersonate}!\.\root\default:StdRegProv" _
).EnumValues( _
HKEY_CURRENT_USER, SUB_KEY, values _
)
Dim outputFile
Set outputFile = fso.OpenTextFile( _
fso.BuildPath( _
OUTPUT_PATH, shell.ExpandEnvironmentStrings("%username%") & ".txt" _
) _
, ForAppending _
, True _
)
Dim value
If Not IsNull(values) Then
For Each value In values
Call outputFile.WriteLine(fso.GetAbsolutePathName( value ))
Next
End If
Call outputFile.Close()
我目前正在尝试用 cmd 脚本替换 powershell 脚本,因为它更适合我正在尝试完成的工作。
在 Powershell 中,我使用这段代码 return 计算机上的个人文件夹目录列表
$Name = [Environment]::UserName
get-item HKCU:\software\Microsoft\Office.0\Outlook\Search\Catalog - ErrorAction SilentlyContinue | select -expandProperty property | Out-File Z:\global\pst\PowershellOutput$Name.txt -append
这就是我想要的,并输出一个目录列表,就像这样
H:\PST\My Outlook Data File 1.pst
H:\PST\My Outlook Data File 2.pst
C:\PST\My Outlook Data File 3.pst
但是当我运行这一行提取注册表项时
regedit.exe /e Z:\global\battest\%username%.txt "HKEY_CURRENT_USER\Software\Microsoft\Office.0\Outlook\Search\Catalog"
我得到一个包含大量不必要数据的输出
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Office.0\Outlook\Search\Catalog]
"H:\PST\My Outlook Data File 1.pst"=hex:0c,01,00,00,00,00,00,00
"H:\PST\My Outlook Data File 2.pst"=hex:f8,00,00,00,00,00,00,00
"C:\PST\My Outlook Data File 3.pst"=hex:ac,02,00,00,00,00,00,00
此数据被传递到另一个程序*,因此解决方法是使用“”标记内的数据,但它也有双反斜杠,这使得数据难以传递。
有没有更好的方法在 CMD 中获取这些值,或者我错过了一个只显示目录的参数?
- -很抱歉之前没有包括这个但是这个程序不是 CMD 程序,它是 visual basic
您可能需要使用 REG QUERY 命令。在单个 bat 文件中,它会像:
@echo OFF
for /f "usebackq tokens=1-3" %%A in (`REG QUERY "HKCU\Software\Microsoft\Office.0\Outlook\Search\Catalog"`) do (
set ValueName=%%A
)
echo %ValueName% > Z:\global\battest\%username%.txt
从 How can I get the value of a registry key from within a batch script?
得到这个这是一个批处理代码,用于获取 *.pst 文件(不是目录)的列表,这些代码独立于 *.pst 文件的数量及其文件名,只要文件名以 .pst
.
@echo off
setlocal EnableExtensions EnableDelayedExpansion
for /F "skip=1 delims=" %%# in ('%SystemRoot%\System32\reg.exe query HKCU\Software\Microsoft\Office.0\Outlook\Search\Catalog 2^>nul') do (
set "RegData=%%#"
set "DelData=!RegData:*.pst=!"
if not "!DelData!" == "!RegData!" call :OutputFileName
)
endlocal
goto :EOF
:OutputFileName
set "RegData=!RegData:%DelData%=!"
echo !RegData:~4!
goto :EOF
*.pst 文件是 Outlook 个人存储文件,是电子邮件、联系人的容器文件,...
命令 FOR 运行控制台应用程序 REG 以查询注册表项的所有值:
HKEY_CURRENT_USER\Software\Microsoft\Office.0\Outlook\Search\Catalog
在 Windows Vista 和更新的 Windows 版本上的输出是为了示例:
HKEY_CURRENT_USER\Software\Microsoft\Office.0\Outlook\Search\Catalog
H:\PST\My Outlook Data File 1.pst REG_SZ whatever the
H:\PST\My Outlook Data File 2.pst REG_SZ data value is
C:\PST\My Outlook Data File 3.pst REG_SZ of each value
输出注册表项,然后是注册表值,每个注册表值缩进 4 个空格,值名称和值类型之间有 4 个空格,值类型和数据值之间有 4 个空格。
但在 Windows XP 上,输出为示例:
! REG.EXE VERSION 3.0
HKEY_CURRENT_USER\Software\Microsoft\Office.0\Outlook\Search\Catalog
H:\PST\My Outlook Data File 1.pst REG_SZ whatever the
H:\PST\My Outlook Data File 2.pst REG_SZ data value is
C:\PST\My Outlook Data File 3.pst REG_SZ of each value
因此在注册表项之前有前两行 header。注册表值也缩进了 4 个空格。但是值名称和值类型之间有 1 个或多个制表符而不是空格,并且值类型和数据值之间也有 1 个或多个制表符而不是空格。
注:不知道REG_SZ
是不是正确的注册表值类型。我的 Windows 注册表中根本没有此注册表项,因此只添加了 3 个注册表值作为带有虚拟字符串的字符串值。
所以棘手的部分是如何获取还包含空格的注册表值名称,以获取独立于文件名的 *.pst 文件的名称。
这是通过将每个输出行分配给环境变量 skip=1
的第一行除外,然后从该行获取下一个分配给环境的 .pst
之后的所有内容变量 DelData
.
如果该行在任何情况下都包含 .pst
导致 DelData
的值不等于 RegData
的值,则进一步调用子例程 OutputFileName
处理并打印 *.pst 文件的文件名。
在子例程 OutputFileName
中,首先使用字符串替换从 RegData
中删除 *.pst 文件名右侧的字符串。接下来输出*.pst文件名,开头没有4个缩进空格。
如果缩进空格数不总是恰好是 4 个空格,行 echo !RegData:~4!
可以替换为以下代码以独立于缩进数 spaces/tabs.
for /F "tokens=1*" %%I in ("%RegData%") do (
if "%%J" == "" (
echo %%I
) else (
echo %%I %%J
)
)
使用 REG 而不是 REGEDIT 的优点是 运行 不需要提升管理员权限这个批号。
要了解使用的命令及其工作原理,请打开命令提示符 window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
call /?
echo /?
for /?
goto /?
reg /?
reg query /?
set /?
setlocal /?
如果注册表项不存在,则不输出任何内容。通过使用 2^>nul
将其重定向到设备 NUL,此处抑制了处理 STDERR 的错误消息输出。有关详细信息,请参阅 Microsoft 文章 Using command redirection operators。重定向运算符 >
必须在此处使用脱字符 ^
进行转义,以便在解析 FOR 命令行时被解释为文字字符,并在执行时被解释为重定向运算符REG 命令行的 FOR.
虽然我没有安装 Office 进行测试,但这应该可以完成工作
@echo off
setlocal enableextensions disabledelayedexpansion
set "HKCU=&H80000001"
set "subKey=software\Microsoft\Office.0\Outlook\Search\Catalog"
>> "Z:\global\pst\PowershellOutput\%username%.txt" (
for /f "tokens=2 delims={" %%a in ('
wmic
/NameSpace:\root\default
Class StdRegProv
Call EnumValues
hDefKey^="%HKCU%"
sSubKeyName^="%subkey%"
2^>nul
^| find "sNames = {"
') do for %%b in (%%a) do (
for /f delims^=^" %%c in ("%%~b") do echo(%%~fc
)
)
它使用 wmic
检索指定键下定义的值列表,并过滤输出以仅检索具有格式为 sNames = {"v1", "v2", "v3"}
.[=19 的这些值的名称的行=]
{
用于将行的开头与值列表 (%%a
) 分开,并迭代此列表 (%%b
) 以获取每个值。列表中的最后一个元素包含需要删除的结尾 }
,这由 %%c
使用值中的引号作为分隔符处理。
等效的 vbs 版本可以是
Option Explicit
Const HKEY_CURRENT_USER = &H80000001
Const ForAppending = 8
Const SUB_KEY = "software\Microsoft\Office.0\Outlook\Search\Catalog"
Const OUTPUT_PATH = "Z:\global\pst\PowershellOutput"
Dim fso, shell
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Set shell = WScript.CreateObject("WScript.Shell")
Dim values
Call GetObject( _
"winmgmts:{impersonationLevel=impersonate}!\.\root\default:StdRegProv" _
).EnumValues( _
HKEY_CURRENT_USER, SUB_KEY, values _
)
Dim outputFile
Set outputFile = fso.OpenTextFile( _
fso.BuildPath( _
OUTPUT_PATH, shell.ExpandEnvironmentStrings("%username%") & ".txt" _
) _
, ForAppending _
, True _
)
Dim value
If Not IsNull(values) Then
For Each value In values
Call outputFile.WriteLine(fso.GetAbsolutePathName( value ))
Next
End If
Call outputFile.Close()