使用 for 循环(批处理脚本)从 Windows XP 中的目录输出中提取详细信息
Extract details from dir output in Windows XP using for loop (batch script)
我正在尝试理解批处理脚本中的 for
循环;特别是 skip
和 tokens
参数。我在 followed by this nice .
中找到了一个很好的例子
我想看看如何从 Windows XP 中的 dir
中提取日期和时间 [=17] =] 输出(参见下面的示例输出)与 Windows 7. 换句话说,如何在 Windows XP 中提取特定文件夹的创建日期。
来自上述链接的以下修改代码在 Windows 7 中正确提取了 DIR
的日期和时间,但在 Windows XP 中失败(即提取其他字符):
SETLOCAL ENABLEDELAYEDEXPANSION
set "path_of_folder=C:\folderA\folderB"
for /f "skip=5 tokens=1,2,4 delims= " %%a in (
'dir /ad /tc "%path_of_folder%\."') do IF "%%c"=="." (
set "dt=%%a"
set dirdate=%%a
set dirtime=%%b
echo !dirdate!, !dirtime!
set dirday=!dirdate:~0,2!
echo !dirday!
)
在 Windows 7 命令提示符中的 dir
命令输出类似于:
Directory of C:\Windows
12/21/2016 12:56 <DIR> .
12/21/2016 12:56 <DIR> ..
09/18/2017 07.42 678 config
在 Windows XP 中,命令提示符中的 dir
命令输出类似于:
Directory of C:\WINDOWS
12/21/2016 12:56 PM <DIR> .
12/21/2016 12:56 PM <DIR> ..
09/18/2017 07.42 PM 678 config
唯一的区别(据我所知)是 PM
列 (?) 它在 Windows 7 中不存在,但在 [=49 中存在=] XP.
我知道这可能是一个微不足道的问题,但我是批处理脚本的新手,看到一个使用复杂 for
循环的具体示例将有助于我的理解。 假设使用延迟扩展。
dir
命令时间格式取决于控制面板中的设置。
要获得独立于控制面板设置的目录创建时间,您可以使用 dirtimejs.bat:
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set "path_of_folder=C:\folderA\folderB"
for /f "tokens=1* delims=:" %%a in ('dirtimejs.bat "%path_of_folder%" ^| find "Created :"') do (
for /f "tokens=1,2,3,4,5,6 delims=:- " %%A in ("%%b") do (
echo dir year: %%A
echo dir month : %%B
echo dir day : %%C
)
)
要查看什么信息 dirtimejs
尝试使用 dirtimejs.bat "%path_of_folder%"
。
windows 列表中提供的时间格式取决于用户设置。不幸的是,您发布的是经过篡改的列表,而不是实际数据(证据 - 列出的每个数据元素的时间和日期完全相同,禁止 PM
标志,尽管据称它们在不同的系统上)
修复:简单的方法是调整系统的 UI 设置 - 在两台机器上使用相同的格式。
应对代码:
@ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
SET "required_format=12"
for /f "tokens=1-5 delims= " %%a in (
'type q44964366.txt^|FINDSTR /L /E /c:" ."') do (
set "dt=%%a"
set dirdate=%%a
set dirtime=%%b
IF "%%e"=="." (
REM reading 12-hr format - convert to 24-hr
IF "!dirtime:~0,2!"=="12" (
IF /i "%%c"=="PM" (
SET "dirtime=12!dirtime:~2!"
) else (
SET "dirtime=00!dirtime:~2!"
)
) ELSE (
IF /i "%%c"=="PM" (
SET /a $=2!dirtime:~0,2!-88
SET "dirtime=!$:~-2!!dirtime:~2!"
)
)
)
REM else is in 24-hr format already
IF %required_format%==12 (
SET /a $=1!dirtime:~0,2!
IF !$!==100 SET "dirtime=12!dirtime:~2! AM"
IF !$! gtr 100 IF !$! leq 111 SET "dirtime=!dirtime! AM"
IF !$!==112 SET "dirtime=12!dirtime:~2! PM"
IF !$! gtr 112 SET /a $=$-12&SET "dirtime=!$:~-2!!dirtime:~2! PM"
)
echo !dirdate!, !dirtime!
set dirday=!dirdate:~0,2!
echo !dirday!
)
GOTO :EOF
为了测试,我使用了一个包含典型 dir
行的文件。您需要用原来的 dir
命令替换 type q44964366.txt
竖线 (|
) 之前的插入符号 (^
) 告诉 cmd
竖线是要执行的命令的一部分。管道输出数据(来自 dir
命令)并用常量字符串填充所有 /L
字面上 /E
结束 /c:"string"
的行 - 请注意这是 Space. 它巧妙地过滤掉了 .
目录名以外的所有内容,因此继续分析 [=22] 上的处理=] 名称 - 这是 findstr
允许通过的唯一名称...
既然我们现在使用的是tokens=1-5
,那么如果线路是12小时格式,那么%%e
只能设置为.
,否则是24小时格式。要转换为 24 小时格式,我们需要查看 %%c
是否为 PM
(否则为 AM
),如果是,则将小时数加 12 except for 12
in the hours digits, 当我们需要将 hours digits 设置为 00
for AM
和 12
for PM
.
这些转换中的最后一个很明显,但对于非 12:xx PM,我们采用两个小时数字并将它们附加到 2
,从而形成一个字符串 2hh
。 cmd
数学将任何以 0
开头的数字视为八进制,因此 09:xx
会产生错误。 209
它可以应付十进制。从中减去 88,即 100-12。这将生成一个 3 位数字,批处理将其视为字符串,我们需要最后 2 个字符。
您未指定首选格式,因此我们可能需要转换为 12 小时制(在代码中,如果已在 required_format
中选择)
在12小时模式下,如果时间是下午,我们需要减去12小时,并注意特殊值12:xx
和00:xx
。这也是通过将时间的前 2 位数字串成一个常量以形成一个漂亮的 3 位十进制值来完成的。 100 表示 12:xx AM
112 表示 12:xx PM
101-111 表示我们只需要添加 AM
如果它大于 112(例如 15:xx 24 小时格式)那么我们需要减去 12 并将结果的最后 2 个字符作为小时数字;然后添加 PM
.
完成。
type q44964366.txt
由原来的
中的 dir
命令替换
'dir /ad /tc "%path_of_folder%."^|FINDSTR /L /E /c:" ."') 做 (
不同的 OS 不是你的问题,不幸的是 DIR
命令的输出不一致,它可能因用户而异 。最简单的解决方法是使用另一种方法来检索您希望捕获的数据, 使用 JScript,以下答案使用另一个内置工具,WMIC.exe
.
@Echo Off
Set "_dp=C:\folderA\folderB"
Echo Directory of %_dp% & Echo(
For %%A In ("%_dp%\*") Do (Set "_pf=%%~fA"
SetLocal EnableDelayedExpansion
For /F "UseBackQ Skip=1 Delims=" %%B In (`WMIC DataFile Where^
"Drive='%%~dA' And Name='!_pf:\=\!'" Get CreationDate^,FileSize`
) Do For /F "Tokens=1-2*" %%C In ("%%~B") Do (Set "_dt=%%~nxC"
Set "_d=!_dt:~4,2!/!_dt:~6,2!/!_dt:~,4!"
Set "_t=!_dt:~8,2!:!_dt:~10,2!" & Echo !_d! !_t! %%D "%%~nxA")
EndLocal)
Pause
编辑
看来,您正在寻找来自 dir
目录的数据。 (我误以为你指的是 dir
命令).
下面是一些更新的代码以充分反映这一点:
@Echo Off
Set "_dp=C:\folderA\folderB"
Echo Directory of %_dp% & Echo(
For /D %%A In ("%_dp%\*") Do (Set "_pf=%%~fA"
SetLocal EnableDelayedExpansion
For /F "Skip=1 Delims=" %%B In ('
"WMIC FSDir Where (Drive='%%~dA' And Name='!_pf:\=\!') Get CreationDate"
') Do For /F %%C In ("%%~B") Do (Set "_dt=%%~nxC"
Set "_d=!_dt:~4,2!/!_dt:~6,2!/!_dt:~,4!"
Set "_t=!_dt:~8,2!:!_dt:~10,2!" & Echo !_d! !_t! "%%~nxA")
EndLocal)
Pause
据我所知,第一次在 XP 中 运行 WMIC 可能会有初始化延迟
可以操纵输出布局,正如我所做的那样……
我正在尝试理解批处理脚本中的 for
循环;特别是 skip
和 tokens
参数。我在
我想看看如何从 Windows XP 中的 dir
中提取日期和时间 [=17] =] 输出(参见下面的示例输出)与 Windows 7. 换句话说,如何在 Windows XP 中提取特定文件夹的创建日期。
来自上述链接的以下修改代码在 Windows 7 中正确提取了 DIR
的日期和时间,但在 Windows XP 中失败(即提取其他字符):
SETLOCAL ENABLEDELAYEDEXPANSION
set "path_of_folder=C:\folderA\folderB"
for /f "skip=5 tokens=1,2,4 delims= " %%a in (
'dir /ad /tc "%path_of_folder%\."') do IF "%%c"=="." (
set "dt=%%a"
set dirdate=%%a
set dirtime=%%b
echo !dirdate!, !dirtime!
set dirday=!dirdate:~0,2!
echo !dirday!
)
在 Windows 7 命令提示符中的 dir
命令输出类似于:
Directory of C:\Windows
12/21/2016 12:56 <DIR> .
12/21/2016 12:56 <DIR> ..
09/18/2017 07.42 678 config
在 Windows XP 中,命令提示符中的 dir
命令输出类似于:
Directory of C:\WINDOWS
12/21/2016 12:56 PM <DIR> .
12/21/2016 12:56 PM <DIR> ..
09/18/2017 07.42 PM 678 config
唯一的区别(据我所知)是 PM
列 (?) 它在 Windows 7 中不存在,但在 [=49 中存在=] XP.
我知道这可能是一个微不足道的问题,但我是批处理脚本的新手,看到一个使用复杂 for
循环的具体示例将有助于我的理解。 假设使用延迟扩展。
dir
命令时间格式取决于控制面板中的设置。
要获得独立于控制面板设置的目录创建时间,您可以使用 dirtimejs.bat:
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set "path_of_folder=C:\folderA\folderB"
for /f "tokens=1* delims=:" %%a in ('dirtimejs.bat "%path_of_folder%" ^| find "Created :"') do (
for /f "tokens=1,2,3,4,5,6 delims=:- " %%A in ("%%b") do (
echo dir year: %%A
echo dir month : %%B
echo dir day : %%C
)
)
要查看什么信息 dirtimejs
尝试使用 dirtimejs.bat "%path_of_folder%"
。
windows 列表中提供的时间格式取决于用户设置。不幸的是,您发布的是经过篡改的列表,而不是实际数据(证据 - 列出的每个数据元素的时间和日期完全相同,禁止 PM
标志,尽管据称它们在不同的系统上)
修复:简单的方法是调整系统的 UI 设置 - 在两台机器上使用相同的格式。
应对代码:
@ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
SET "required_format=12"
for /f "tokens=1-5 delims= " %%a in (
'type q44964366.txt^|FINDSTR /L /E /c:" ."') do (
set "dt=%%a"
set dirdate=%%a
set dirtime=%%b
IF "%%e"=="." (
REM reading 12-hr format - convert to 24-hr
IF "!dirtime:~0,2!"=="12" (
IF /i "%%c"=="PM" (
SET "dirtime=12!dirtime:~2!"
) else (
SET "dirtime=00!dirtime:~2!"
)
) ELSE (
IF /i "%%c"=="PM" (
SET /a $=2!dirtime:~0,2!-88
SET "dirtime=!$:~-2!!dirtime:~2!"
)
)
)
REM else is in 24-hr format already
IF %required_format%==12 (
SET /a $=1!dirtime:~0,2!
IF !$!==100 SET "dirtime=12!dirtime:~2! AM"
IF !$! gtr 100 IF !$! leq 111 SET "dirtime=!dirtime! AM"
IF !$!==112 SET "dirtime=12!dirtime:~2! PM"
IF !$! gtr 112 SET /a $=$-12&SET "dirtime=!$:~-2!!dirtime:~2! PM"
)
echo !dirdate!, !dirtime!
set dirday=!dirdate:~0,2!
echo !dirday!
)
GOTO :EOF
为了测试,我使用了一个包含典型 dir
行的文件。您需要用原来的 dir
命令替换 type q44964366.txt
竖线 (|
) 之前的插入符号 (^
) 告诉 cmd
竖线是要执行的命令的一部分。管道输出数据(来自 dir
命令)并用常量字符串填充所有 /L
字面上 /E
结束 /c:"string"
的行 - 请注意这是 Space. 它巧妙地过滤掉了 .
目录名以外的所有内容,因此继续分析 [=22] 上的处理=] 名称 - 这是 findstr
允许通过的唯一名称...
既然我们现在使用的是tokens=1-5
,那么如果线路是12小时格式,那么%%e
只能设置为.
,否则是24小时格式。要转换为 24 小时格式,我们需要查看 %%c
是否为 PM
(否则为 AM
),如果是,则将小时数加 12 except for 12
in the hours digits, 当我们需要将 hours digits 设置为 00
for AM
和 12
for PM
.
这些转换中的最后一个很明显,但对于非 12:xx PM,我们采用两个小时数字并将它们附加到 2
,从而形成一个字符串 2hh
。 cmd
数学将任何以 0
开头的数字视为八进制,因此 09:xx
会产生错误。 209
它可以应付十进制。从中减去 88,即 100-12。这将生成一个 3 位数字,批处理将其视为字符串,我们需要最后 2 个字符。
您未指定首选格式,因此我们可能需要转换为 12 小时制(在代码中,如果已在 required_format
中选择)
在12小时模式下,如果时间是下午,我们需要减去12小时,并注意特殊值12:xx
和00:xx
。这也是通过将时间的前 2 位数字串成一个常量以形成一个漂亮的 3 位十进制值来完成的。 100 表示 12:xx AM
112 表示 12:xx PM
101-111 表示我们只需要添加 AM
如果它大于 112(例如 15:xx 24 小时格式)那么我们需要减去 12 并将结果的最后 2 个字符作为小时数字;然后添加 PM
.
完成。
type q44964366.txt
由原来的
dir
命令替换
'dir /ad /tc "%path_of_folder%."^|FINDSTR /L /E /c:" ."') 做 (
不同的 OS 不是你的问题,不幸的是 DIR
命令的输出不一致,它可能因用户而异 。最简单的解决方法是使用另一种方法来检索您希望捕获的数据,WMIC.exe
.
@Echo Off
Set "_dp=C:\folderA\folderB"
Echo Directory of %_dp% & Echo(
For %%A In ("%_dp%\*") Do (Set "_pf=%%~fA"
SetLocal EnableDelayedExpansion
For /F "UseBackQ Skip=1 Delims=" %%B In (`WMIC DataFile Where^
"Drive='%%~dA' And Name='!_pf:\=\!'" Get CreationDate^,FileSize`
) Do For /F "Tokens=1-2*" %%C In ("%%~B") Do (Set "_dt=%%~nxC"
Set "_d=!_dt:~4,2!/!_dt:~6,2!/!_dt:~,4!"
Set "_t=!_dt:~8,2!:!_dt:~10,2!" & Echo !_d! !_t! %%D "%%~nxA")
EndLocal)
Pause
编辑
看来,您正在寻找来自 dir
目录的数据。 (我误以为你指的是 dir
命令).
下面是一些更新的代码以充分反映这一点:
@Echo Off
Set "_dp=C:\folderA\folderB"
Echo Directory of %_dp% & Echo(
For /D %%A In ("%_dp%\*") Do (Set "_pf=%%~fA"
SetLocal EnableDelayedExpansion
For /F "Skip=1 Delims=" %%B In ('
"WMIC FSDir Where (Drive='%%~dA' And Name='!_pf:\=\!') Get CreationDate"
') Do For /F %%C In ("%%~B") Do (Set "_dt=%%~nxC"
Set "_d=!_dt:~4,2!/!_dt:~6,2!/!_dt:~,4!"
Set "_t=!_dt:~8,2!:!_dt:~10,2!" & Echo !_d! !_t! "%%~nxA")
EndLocal)
Pause
据我所知,第一次在 XP 中 运行 WMIC 可能会有初始化延迟
可以操纵输出布局,正如我所做的那样……