我有一个批处理文件,可以使用gsutil工具将一些本地文件复制到google存储区。 gsutil工具会生成一个漂亮的日志文件,其中显示了上载的文件的详细信息以及是否正常。
Source,Destination,Start,End,Md5,UploadId,Source Size,Bytes Transferred,Result,Description
file://C:\TEMP\file_1.xlsx,gs://app1/backups/file_1.xlsx,2018-12-04T15:25:48.428000Z,2018-12-04T15:25:48.804000Z,CPHHZfdlt6AePAPz6JO2KQ==,,18753,18753,OK,
file://C:\TEMP\file_2.xlsx,gs://app1/backups/file_2.xlsx,2018-12-04T15:25:48.428000Z,2018-12-04T15:25:48.813000Z,aTKCOQSPVwDycM9+NGO28Q==,,18753,18753,OK,
我想做的就是
问题是源文件名后面附加了“ file://”,例如,我似乎无法删除
file://C:\TEMP\file_1.xlsx
需要更改为此
C:\TEMP\file_1.xlsx
我正在使用for / f循环,不确定在%f / f循环中变量%% A的操作是否不同。
@echo off
rem copy the gsutil log file into a temp file and remove the header row using the 'more' command.
more +1 raw_results.log > .\upload_results.log
rem get the source file name (column 1) and the upload result (OK) from column 8
for /f "tokens=1,8 delims=," %%A in (.\upload_results.log) do (
echo The source file is %%A , the upload status was %%B
set line=%%A
set line=!line:file://:=! >> output2.txt echo !line!
echo !line!
)
输出是这样的。
The source file is file://C:\TEMP\file_1.xlsx , the upload status was OK
The source file is file://C:\TEMP\file_2.xlsx , the upload status was OK
我希望它可以将更改后的值转储到新文件中,但目前不产生任何结果。 通常,我会使用类似这样的方法将特定字符提取到字符串的末尾,但不适用于For / f循环。
%var:~7%
非常感谢任何指针或其他实现方法。
答案 0 :(得分:3)
由于要删除的部分似乎固定,因此使用子字符串更加容易。
还使用for /f "skip=1"
避免了使用外部命令+1和另一个中间文件的必要。
@echo off & setlocal EnableDelayedExpansion
type NUL>output2.txt
for /f "skip=1 eol=| tokens=1,8 delims=," %%A in (.\upload_results.log) do (
echo The source file is %%A , the upload status was %%B
set "line=%%A"
set "line=!line:~7!"
echo(!line!>>output2.txt
echo(!line!
)
答案 1 :(得分:1)
文件名和路径也可以包含一个或多个感叹号。 Windows命令处理器第二次对行set line=%%A
进行解析,然后执行启用延迟扩展的命令。请参见How does the Windows Command Interpreter (CMD.EXE) parse scripts?,在此行上,分配给循环变量!
的字符串中的每个A
都被解释为延迟的扩展环境变量引用的开始或结束。因此,如果文件路径/名称包含一个或多个感叹号,则将循环变量A
的字符串分配给环境变量line
,并且进行了不必要的修改。
因此,最好避免使用延迟扩展。最快的解决方案是使用第二个 FOR 来完成此任务,以从分配给循环变量file://
的字符串中删除A
。
@echo off
del output2.txt 2>nul
for /F "skip=1 tokens=1,8 delims=," %%A in (upload_results.log) do (
echo The source file is %%A , the upload status was %%B.
for /F "tokens=1* delims=/" %%C in ("%%~A") do echo %%D>>output2.txt
)
如果没有循环内的第一个echo
命令行,甚至更快:
@echo off
(for /F "skip=1 delims=," %%A in (upload_results.log) do (
for /F "tokens=1* delims=/" %%B in ("%%~A") do echo %%C
))>output2.txt
第二种解决方案也可以编写为单个命令行:
@(for /F "skip=1 delims=," %%A in (upload_results.log) do @for /F "tokens=1* delims=/" %%B in ("%%~A") do @echo %%C)>output2.txt
所有解决方案都执行以下操作:
外部 FOR 处理ANSI(每个字符固定一个字节)或UTF-8(每个字符固定一到四个字节)编码的文本 file upload_results.log
行逐行跳过第一行,而忽略总是空的行和以分号开头的行(在此不会出现)。
通过将第一个逗号分隔的字符串分配给指定的循环变量A
,在每次出现一个或多个逗号时将该行拆分为子字符串(令牌)。第一种解决方案还根据ASCII table将第八个逗号分隔的字符串分配给下一个循环变量B
。
内部 FOR 使用A
作为字符串定界符来处理分配给循环变量/
的字符串,以分配给指定的循环变量{ {1}},然后根据ASCII表转到下一个循环变量,即在第一个正斜杠序列之后的字符串的其余部分,即完整的合格文件名。
使用命令file:
输出完整的合格文件名,并将其直接附加到文件echo
(第一个解决方案)或首先附加到内存缓冲区,该缓冲区最后立即写入文件{{1} }覆盖当前目录中该文件名可能已经存在的文件。
要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。
output2.txt
output2.txt
del /?
有关重定向echo /?
,for /?
和>
的解释,另请参阅Microsoft关于Using command redirection operators的文章