我正在编写一个
Windows
批处理文件,并且 batch file
应该在特定文件夹中输出文件。我希望文件名写成如下:
filename-yyyymmdd.csv
其中 yyyymmdd 代表当前日期。
我的
batch file
代码如下:
cd:\Program Files\Microsoft SQL Server\Client SDK\ODBC\110\Tools\Binn
bcp "SELECT TOP 100 * FROM xxxx.dbo.xxxxx" queryout c:\test\csv\confirmed.csv -t, -c -S xxxx\xxxxx -U xxx -P xxxxxxxxxx
set mydate=%date:~10,4%%date:~4,2%%date:~7,2%
echo %mydate%
copy c:\test\csv\confirmed.csv c:\test\csvwithdates\confirmed-%mydate%.csv
我得到以下文件名作为输出:
confirmed-ay18.csv
所需输出:
confirmed-20180528.csv
我查看了以下关于
StackOverflow
的问题,但我很难实施建议的答案:
我做错了什么?
动态环境变量
DATE
以区域相关格式提供当前本地日期,即根据 Windows 区域和所用帐户的语言选项中设置的国家/地区。维基百科文章按国家/地区列出的日期格式列出了世界各国使用的各种日期格式。
因此有必要使用在命令提示符窗口中运行批处理文件时使用的帐户运行
echo %DATE%
并查看输出日期字符串。
输出日期是以缩写工作日开头还是输出日期不带工作日?第一个输出日和下个月是数字还是第一个输出月和下一天?月份输出是数字还是名称?月份中的某一天或值小于 10 的月份输出是否带有前导 0,因此始终使用两位数或仅使用一位数?
用于将
ddd, dd.MM.yyyy
格式的区域相关日期字符串修改为 .
或 /
或任何其他分隔符为 yyyyMMdd
的非常常见的命令行是:
set "LocalDate=%DATE:~-4%%DATE:~-7,2%%DATE:~-10,2%"
日期字符串从右侧替换,以使字符串替换独立于日期字符串开头是否存在工作日。
对于区域相关的日期字符串
ddd, MM/dd/yyyy
使用的命令行是:
set "LocalDate=%DATE:~-4%%DATE:~-10,2%%DATE:~-7,2%"
可以通过使用命令 ECHO 而不是 SET 在命令提示符窗口中运行命令来轻松找出需要替换的字符串:
echo %DATE%
echo %DATE:~-4%%DATE:~-7,2%%DATE:~-10,2%
echo %DATE:~-4%%DATE:~-10,2%%DATE:~-7,2%
另请参阅 %date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2% 是什么意思意思是?
使用动态环境变量
DATE
的优点是速度,因为Windows命令处理器非常快地完成此字符串替换。缺点是由于地区/国家的依赖性,日期格式会有所不同。
独立于区域的解决方案使用命令 WMIC,如下所示:
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "LocalDate=%%I"
set "LocalDate=%LocalDate:~0,8%"
WMIC 始终以 yyyyMMddHHmmss.microsecond±UTC 偏移量(以分钟为单位) 输出日期字符串,与配置的国家/地区以及为该国家/地区设置的日期格式无关。
使用WMIC的缺点是执行所需的时间,因为它需要超过一秒的时间来输出由命令FOR接下来处理的UTF-16 Little Endian编码的日期字符串。
请参阅答案为什么 %date% 在按计划任务执行的批处理文件中产生不同的结果?,了解有关这两个命令行在 Windows 命令处理器执行时如何工作的详细说明
cmd.exe
。
完整的批处理文件:
@echo off
cd /D "C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\110\Tools\Binn"
bcp.exe "SELECT TOP 100 * FROM xxxx.dbo.xxxxx" queryout C:\test\csv\confirmed.csv -t, -c -S xxxx\xxxxx -U xxx -P xxxxxxxxxx
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "LocalDate=%%I"
set "LocalDate=%LocalDate:~0,8%"
copy /Y C:\test\csv\confirmed.csv C:\test\csvwithdates\confirmed-%LocalDate%.csv
set "LocalDate="
WMIC解决方案的另一个缺点是它无法再默认安装在最新的 Windows 10/11 上,因为 Microsoft 声明此可执行文件已弃用,并且它成为一个可选的 Windows 组件,默认情况下不再安装在最新的 Windows 上10/11 未安装默认已安装 wmic.exe
的旧版 Windows 升级版。另一个与区域无关的解决方案是使用
ROBOCOPY 的错误输出:
set "LocalDate=" & for /F "tokens=1-3 delims=/ " %%G in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do if not defined LocalDate set "LocalDate=%%G%%H%%I"
答案中详细解释了此命令行午夜后时间设置不正确。它需要 %SystemRoot%\System32\robocopy.exe
,从 Windows Vista 和 Windows Server 2003 开始默认存在于 Windows
System32
目录中。Windows Server 2003 的
robocopy.exe
可以复制到 Windows XP 的 Windows
System32
目录中。此解决方案的完整批处理文件是:
@echo off
cd /D "C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\110\Tools\Binn"
bcp.exe "SELECT TOP 100 * FROM xxxx.dbo.xxxxx" queryout C:\test\csv\confirmed.csv -t, -c -S xxxx\xxxxx -U xxx -P xxxxxxxxxx
set "LocalDate=" & for /F "tokens=1-3 delims=/ " %%G in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do if not defined LocalDate set "LocalDate=%%G%%H%%I"
copy /Y C:\test\csv\confirmed.csv C:\test\csvwithdates\confirmed-%LocalDate%.csv
set "LocalDate="
要了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。
cd /?
copy /?
echo /?
for /?
robocopy /?
set /?
wmic /?
wmic os /?
wmic os get /?
wmic os get localdatetime /?