如何从网络用户帐户中过滤主目录位置?
How to filter Home Directory location from net user accounts?
有命令 net user
列出所有 用户帐户。
命令的输出是这样的:
Administrator Guest asroot
1psaadm 2satish 3shyam
4sushil 5sysuser_8 6sysuser_b
tcuser test1 test11
...
如果我运行这个命令
net user shyam
输出是:
Workstations allowed All
Logon script
User profile
Home directory C:\Inetpub\vhosts\example.com
Last logon 6/5/2021 4:57:17 AM
Logon hours allowed All
我只想要来自所有 user accounts
的 Home Directory
路径。所以我希望所有用户帐户 只有这条路径 C:\Inetpub\vhosts\example.com
。
我试图用这个命令得到想要的数据,但是没有输出。
for /f "tokens=* skip=1" %a in ('wmic UserAccount get Name') do net user %a | findstr /c:"Home directory"
如何获取所有用户帐户的所有路径列表?
注意:如果你的cmd中没有Home directory
路径那么你可以尝试列出:
Logon hours allowed ALL
WMIC 的输出始终是 Unicode 输出,编码 UTF-16 LE (little endian) with BOM (byte order mark) which is a problem in this case because of the Windows command processor cmd.exe
is designed for processing text data with a character encoding 每个字符仅使用一个字节。 CMD 将以十六进制字节值 0D 00 0A 00
(回车 return + 换行)结尾的 UTF-16 LE 编码行错误解释为 0D 0D 0A
和因此,从捕获的输出中进一步处理的每一行在删除以 0D 0A
.
结尾的行后,末尾都有一个回车符 return
命令行还有一个问题:
wmic UserAccount get Name
WMIC 追加到尾随 space 的所有行,以便每个输出行具有相同数量的字符。这是有问题的,因为用户名也可以包含一个或多个 spaces,因此默认字符串定界符正常 space 和水平制表符不能用于删除不需要的尾随 spaces . tokens=*
的使用导致仅删除所有前导 spaces/tabs,但尾随 space 保留。
使用以下命令行会发生什么情况?
for /f "tokens=* skip=1" %a in ('wmic UserAccount get Name') do
已将一个用户帐户名一个接一个地分配给指定的循环变量 a
,尾随 spaces 并在末尾有一个回车符 return,因此下一个命令未能按预期工作。
在命令提示符中可以使用window:
for /F "skip=2 tokens=1* delims==" %G in ('%SystemRoot%\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2^>nul') do @for /F "eol=| delims=" %I in ("%H") do @for /F "tokens=2*" %J in ('%SystemRoot%\System32\net.exe user "%I" 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Home directory"') do @echo Home directory for "%I" is: "%K"
在批处理文件中可以使用:
for /F "skip=2 tokens=1* delims==" %%G in ('%SystemRoot%\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2^>nul') do for /F "eol=| delims=" %%I in ("%%H") do for /F "tokens=2*" %%J in ('%SystemRoot%\System32\net.exe user "%%I" 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Home directory"') do echo Home directory for "%%I" is: "%%K"
这个长命令行最适合在上面发布的批处理文件中使用,但可读性更好的是:
for /F "skip=2 tokens=1* delims==" %%G in ('%SystemRoot%\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2^>nul') do (
for /F "eol=| delims=" %%I in ("%%H") do (
for /F "tokens=2*" %%J in ('%SystemRoot%\System32\net.exe user "%%I" 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Home directory"') do (
echo Home directory for "%%I" is: "%%K"
)
)
)
带有选项 /F
和包含在 '
中的字符串的第一个命令 FOR 在后台启动另一个带有选项 /c
的命令进程使用完全限定文件名及其四个参数执行 WMIC 重定向 2>nul
重定向来自句柄 STDERR 的可能错误消息(标准错误)到设备 NUL。因此在后台执行,Windows 安装到 C:\Windows
命令:
C:\Windows\System32\cmd.exe /c C:\Windows\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2>nul
阅读有关 Using command redirection operators 的 Microsoft 文档,了解 2>nul
的解释。重定向运算符 >
必须在 FOR 命令行上使用脱字符 ^
进行转义,以便在 Windows 命令解释器处理此命令时将其解释为文字字符执行命令 FOR 之前的行,它在后台启动的单独命令进程中执行嵌入式 wmic
命令行。
WMIC 在这种情况下使用 Microsoft 记录的 Win32_UserAccount class。
最后带有选项 /VALUE
的 WMIC 的输出与没有此选项的输出不同。输出现在针对每个用户帐户名称:
- 两个空行和
- 一行
Name=
和附加的用户帐户名 没有 尾随 spaces,这是使用选项 /VALUE
的原因之一。
WMIC.
在这种情况下最后多输出了两行空行
FOR分别cmd.exe
处理批处理文件等待started的自终止cmd.exe
然后处理捕获的文本数据输出处理后台命令进程的STDOUT(标准输出)。
FOR 选项 /F
总是忽略空行。但是 WMIC 的 Unicode 编码输出不幸地没有被 cmd.exe
正确处理,因此有些行只包含一个回车 return 和以 [= 开头的行35=] 和一个用户帐户名以及末尾的错误回车 return。所以无法直接处理捕获的输出。
选项skip=2 tokens=1* delims==
的使用导致
- 跳过始终为空行的前两行捕获,
- 将每行分成两个子字符串,等号作为字符串定界符在帐户名称感兴趣的行
Name
之后总是存在一次,
- 使用默认的行尾字符
;
这在这里没有问题,因为感兴趣的行总是以 Name
开头
- 并分配给指定的循环变量
G
错误处理的空行上的回车 return 或具有用户帐户名的行上的 Name
和下一个循环变量 H
根据 ASCII table 要么空行上根本没有字符串,要么用户帐户名称末尾有不需要的回车 return。
注意:以一个或多个等号开头的用户帐户名非常不常见,此代码无法正确处理该用户帐户名开头的所有等号也被 FOR 删除。
第二个 FOR 再次使用选项 /F
现在只处理分配给循环变量 H
的字符串。因此,根本没有要处理的字符串分配给 H
,因为空行被错误地解释为带有单个回车 return 的行,因此第二个 FOR 循环过滤器出空行。
对于具有用户帐户名称的行,末尾带有不需要的回车符 return 的名称分配给循环变量 H
由第二个 FOR[=220 处理=] 删除换行符回车 return 并将其余部分分配给指定的循环变量 I
,这是所需的用户帐户名。此处使用选项 eol=|
来避免以一个或多个分号开头的不寻常名称被第二个 FOR 忽略。任何用户帐户名称都不能包含竖线,因为这是 file/folder 名称不允许的字符。
第三个 FOR 循环再次使用选项 /F
运行s 在后台再次执行一个命令进程 NET,输出首先重定向到 FINDSTR,以过滤掉除以 Home directory
区分大小写的行之外的所有行。 NET 输出每个字符编码一个字节的文本数据,从而可以使用 FINDSTR 过滤输出并通过 [=156 处理捕获的输出=]FOR 更容易。后台执行的命令是:
C:\Windows\System32\cmd.exe /c C:\Windows\System32\net.exe user "%%I" 2>nul | C:\Windows\System32\findstr.exe /B /L /C:"Home directory"
第三个 FOR 必须始终只处理以 Home directory
开头的一行,十五个 space 用于对齐,也许仅此而已或主目录为用户帐户定义的路径。使用选项 tokens=2*
使用默认 space/tab 作为行分隔符拆分行,以将单词 directory
分配给指定的循环变量 J
和整个主目录到下一个但一个循环变量 K
的路径,它也可以包含一个或多个 space 或者是一个空字符串,就像在我的 Windows 计算机上的所有帐户一样。
第三个FOR最终执行命令ECHO输出消息,用户账户名由第二个[=156]确定=]FOR 和由第三个 FOR 确定的主目录路径(如果根本没有主目录路径的话)。
Compo suggested to use WMIC with the Win32_NetworkLoginProfile class 通过使用:
%SystemRoot%\System32\wbem\WMIC.exe NetLogin Get Caption,HomeDirectory
那个class有账户名和家目录路径作为成员所以想要的数据可以直接用WMIC.
名称列表在两个 classes 之间是不同的,因为可以在命令提示符 运行ning 两个 WMIC 命令中看到 window 并仔细阅读两个 class 的 属性 Name 的描述,由此 属性 Caption
的字符串 Win32_NetworkLoginProfile
class 也不同于此 class 属性 Name
的字符串。 Caption
的字符串只是真实用户帐户的帐户名称,而 Name
的字符串对于本地帐户是 ComputerName\AccountName 或 Domain\AccountName 对于域帐户。
但是,也许可以在批处理文件中使用此 class 的数据和以下代码:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "skip=2 tokens=1* delims==" %%G in ('%SystemRoot%\System32\wbem\wmic.exe NETLOGIN GET Caption^,HomeDirectory /VALUE 2^>nul') do (
if "%%G" == "Caption" (
set "AccountName="
for /F "eol=| tokens=1,2 delims=\" %%I in ("%%H") do if "%%J" == "" set "AccountName=%%I"
) else if "%%G" == "HomeDirectory" (
set "HomeDirectory="
for /F "eol=| delims=" %%I in ("%%H") do set "HomeDirectory=%%"
if defined AccountName (
setlocal EnableDelayedExpansion
echo Home directory for "!AccountName!" is: "!HomeDirectory!"
endlocal
)
)
)
endlocal
再次出现选项 /VALUE
否则,如果帐户完全没有主目录路径输出,则主目录路径后将再次尾随 spaces 而不是这种情况在我的 Windows 电脑上。
编写代码是为了忽略 Caption
中包含反斜杠的帐户,例如 NT AUTHORITY\SYSTEM
、NT AUTHORITY\LOCAL SERVICE
和 NT AUTHORITY\NETWORK SERVICE
,这些帐户很可能根本不感兴趣。那么,也可以使用 if not "%%I" == "NT AUTHORITY"
而不是 if "%%J" == ""
来过滤掉不感兴趣的帐户,因为它们不是真实用户帐户。
此解决方案的优点是 cmd.exe
仅在后台启动一次 运行 wmic.exe
并获取所有感兴趣的数据。所以这个解决方案更快。
为了了解使用的命令及其工作原理,请打开 command prompt window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
cmd /?
echo /?
endlocal /?
for /?
if /?
net /?
net user /?
set /?
setlocal /?
wmic /?
wmic netlogin /?
wmic netlogin get /?
wmic useraccount /?
wmic useraccount get /?
有命令 net user
列出所有 用户帐户。
命令的输出是这样的:
Administrator Guest asroot
1psaadm 2satish 3shyam
4sushil 5sysuser_8 6sysuser_b
tcuser test1 test11
...
如果我运行这个命令
net user shyam
输出是:
Workstations allowed All
Logon script
User profile
Home directory C:\Inetpub\vhosts\example.com
Last logon 6/5/2021 4:57:17 AM
Logon hours allowed All
我只想要来自所有 user accounts
的 Home Directory
路径。所以我希望所有用户帐户 只有这条路径 C:\Inetpub\vhosts\example.com
。
我试图用这个命令得到想要的数据,但是没有输出。
for /f "tokens=* skip=1" %a in ('wmic UserAccount get Name') do net user %a | findstr /c:"Home directory"
如何获取所有用户帐户的所有路径列表?
注意:如果你的cmd中没有Home directory
路径那么你可以尝试列出:
Logon hours allowed ALL
WMIC 的输出始终是 Unicode 输出,编码 UTF-16 LE (little endian) with BOM (byte order mark) which is a problem in this case because of the Windows command processor cmd.exe
is designed for processing text data with a character encoding 每个字符仅使用一个字节。 CMD 将以十六进制字节值 0D 00 0A 00
(回车 return + 换行)结尾的 UTF-16 LE 编码行错误解释为 0D 0D 0A
和因此,从捕获的输出中进一步处理的每一行在删除以 0D 0A
.
命令行还有一个问题:
wmic UserAccount get Name
WMIC 追加到尾随 space 的所有行,以便每个输出行具有相同数量的字符。这是有问题的,因为用户名也可以包含一个或多个 spaces,因此默认字符串定界符正常 space 和水平制表符不能用于删除不需要的尾随 spaces . tokens=*
的使用导致仅删除所有前导 spaces/tabs,但尾随 space 保留。
使用以下命令行会发生什么情况?
for /f "tokens=* skip=1" %a in ('wmic UserAccount get Name') do
已将一个用户帐户名一个接一个地分配给指定的循环变量 a
,尾随 spaces 并在末尾有一个回车符 return,因此下一个命令未能按预期工作。
在命令提示符中可以使用window:
for /F "skip=2 tokens=1* delims==" %G in ('%SystemRoot%\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2^>nul') do @for /F "eol=| delims=" %I in ("%H") do @for /F "tokens=2*" %J in ('%SystemRoot%\System32\net.exe user "%I" 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Home directory"') do @echo Home directory for "%I" is: "%K"
在批处理文件中可以使用:
for /F "skip=2 tokens=1* delims==" %%G in ('%SystemRoot%\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2^>nul') do for /F "eol=| delims=" %%I in ("%%H") do for /F "tokens=2*" %%J in ('%SystemRoot%\System32\net.exe user "%%I" 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Home directory"') do echo Home directory for "%%I" is: "%%K"
这个长命令行最适合在上面发布的批处理文件中使用,但可读性更好的是:
for /F "skip=2 tokens=1* delims==" %%G in ('%SystemRoot%\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2^>nul') do (
for /F "eol=| delims=" %%I in ("%%H") do (
for /F "tokens=2*" %%J in ('%SystemRoot%\System32\net.exe user "%%I" 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Home directory"') do (
echo Home directory for "%%I" is: "%%K"
)
)
)
带有选项 /F
和包含在 '
中的字符串的第一个命令 FOR 在后台启动另一个带有选项 /c
的命令进程使用完全限定文件名及其四个参数执行 WMIC 重定向 2>nul
重定向来自句柄 STDERR 的可能错误消息(标准错误)到设备 NUL。因此在后台执行,Windows 安装到 C:\Windows
命令:
C:\Windows\System32\cmd.exe /c C:\Windows\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2>nul
阅读有关 Using command redirection operators 的 Microsoft 文档,了解 2>nul
的解释。重定向运算符 >
必须在 FOR 命令行上使用脱字符 ^
进行转义,以便在 Windows 命令解释器处理此命令时将其解释为文字字符执行命令 FOR 之前的行,它在后台启动的单独命令进程中执行嵌入式 wmic
命令行。
WMIC 在这种情况下使用 Microsoft 记录的 Win32_UserAccount class。
最后带有选项 /VALUE
的 WMIC 的输出与没有此选项的输出不同。输出现在针对每个用户帐户名称:
- 两个空行和
- 一行
Name=
和附加的用户帐户名 没有 尾随 spaces,这是使用选项/VALUE
的原因之一。
WMIC.
在这种情况下最后多输出了两行空行FOR分别cmd.exe
处理批处理文件等待started的自终止cmd.exe
然后处理捕获的文本数据输出处理后台命令进程的STDOUT(标准输出)。
FOR 选项 /F
总是忽略空行。但是 WMIC 的 Unicode 编码输出不幸地没有被 cmd.exe
正确处理,因此有些行只包含一个回车 return 和以 [= 开头的行35=] 和一个用户帐户名以及末尾的错误回车 return。所以无法直接处理捕获的输出。
选项skip=2 tokens=1* delims==
的使用导致
- 跳过始终为空行的前两行捕获,
- 将每行分成两个子字符串,等号作为字符串定界符在帐户名称感兴趣的行
Name
之后总是存在一次, - 使用默认的行尾字符
;
这在这里没有问题,因为感兴趣的行总是以Name
开头
- 并分配给指定的循环变量
G
错误处理的空行上的回车 return 或具有用户帐户名的行上的Name
和下一个循环变量H
根据 ASCII table 要么空行上根本没有字符串,要么用户帐户名称末尾有不需要的回车 return。
注意:以一个或多个等号开头的用户帐户名非常不常见,此代码无法正确处理该用户帐户名开头的所有等号也被 FOR 删除。
第二个 FOR 再次使用选项 /F
现在只处理分配给循环变量 H
的字符串。因此,根本没有要处理的字符串分配给 H
,因为空行被错误地解释为带有单个回车 return 的行,因此第二个 FOR 循环过滤器出空行。
对于具有用户帐户名称的行,末尾带有不需要的回车符 return 的名称分配给循环变量 H
由第二个 FOR[=220 处理=] 删除换行符回车 return 并将其余部分分配给指定的循环变量 I
,这是所需的用户帐户名。此处使用选项 eol=|
来避免以一个或多个分号开头的不寻常名称被第二个 FOR 忽略。任何用户帐户名称都不能包含竖线,因为这是 file/folder 名称不允许的字符。
第三个 FOR 循环再次使用选项 /F
运行s 在后台再次执行一个命令进程 NET,输出首先重定向到 FINDSTR,以过滤掉除以 Home directory
区分大小写的行之外的所有行。 NET 输出每个字符编码一个字节的文本数据,从而可以使用 FINDSTR 过滤输出并通过 [=156 处理捕获的输出=]FOR 更容易。后台执行的命令是:
C:\Windows\System32\cmd.exe /c C:\Windows\System32\net.exe user "%%I" 2>nul | C:\Windows\System32\findstr.exe /B /L /C:"Home directory"
第三个 FOR 必须始终只处理以 Home directory
开头的一行,十五个 space 用于对齐,也许仅此而已或主目录为用户帐户定义的路径。使用选项 tokens=2*
使用默认 space/tab 作为行分隔符拆分行,以将单词 directory
分配给指定的循环变量 J
和整个主目录到下一个但一个循环变量 K
的路径,它也可以包含一个或多个 space 或者是一个空字符串,就像在我的 Windows 计算机上的所有帐户一样。
第三个FOR最终执行命令ECHO输出消息,用户账户名由第二个[=156]确定=]FOR 和由第三个 FOR 确定的主目录路径(如果根本没有主目录路径的话)。
Compo suggested to use WMIC with the Win32_NetworkLoginProfile class 通过使用:
%SystemRoot%\System32\wbem\WMIC.exe NetLogin Get Caption,HomeDirectory
那个class有账户名和家目录路径作为成员所以想要的数据可以直接用WMIC.
名称列表在两个 classes 之间是不同的,因为可以在命令提示符 运行ning 两个 WMIC 命令中看到 window 并仔细阅读两个 class 的 属性 Name 的描述,由此 属性 Caption
的字符串 Win32_NetworkLoginProfile
class 也不同于此 class 属性 Name
的字符串。 Caption
的字符串只是真实用户帐户的帐户名称,而 Name
的字符串对于本地帐户是 ComputerName\AccountName 或 Domain\AccountName 对于域帐户。
但是,也许可以在批处理文件中使用此 class 的数据和以下代码:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "skip=2 tokens=1* delims==" %%G in ('%SystemRoot%\System32\wbem\wmic.exe NETLOGIN GET Caption^,HomeDirectory /VALUE 2^>nul') do (
if "%%G" == "Caption" (
set "AccountName="
for /F "eol=| tokens=1,2 delims=\" %%I in ("%%H") do if "%%J" == "" set "AccountName=%%I"
) else if "%%G" == "HomeDirectory" (
set "HomeDirectory="
for /F "eol=| delims=" %%I in ("%%H") do set "HomeDirectory=%%"
if defined AccountName (
setlocal EnableDelayedExpansion
echo Home directory for "!AccountName!" is: "!HomeDirectory!"
endlocal
)
)
)
endlocal
再次出现选项 /VALUE
否则,如果帐户完全没有主目录路径输出,则主目录路径后将再次尾随 spaces 而不是这种情况在我的 Windows 电脑上。
编写代码是为了忽略 Caption
中包含反斜杠的帐户,例如 NT AUTHORITY\SYSTEM
、NT AUTHORITY\LOCAL SERVICE
和 NT AUTHORITY\NETWORK SERVICE
,这些帐户很可能根本不感兴趣。那么,也可以使用 if not "%%I" == "NT AUTHORITY"
而不是 if "%%J" == ""
来过滤掉不感兴趣的帐户,因为它们不是真实用户帐户。
此解决方案的优点是 cmd.exe
仅在后台启动一次 运行 wmic.exe
并获取所有感兴趣的数据。所以这个解决方案更快。
为了了解使用的命令及其工作原理,请打开 command prompt window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
cmd /?
echo /?
endlocal /?
for /?
if /?
net /?
net user /?
set /?
setlocal /?
wmic /?
wmic netlogin /?
wmic netlogin get /?
wmic useraccount /?
wmic useraccount get /?