BAT文件-根据文件内容重命名多个.csv文件

dgiusagp  于 2023-09-28  发布在  其他
关注(0)|答案(1)|浏览(109)

我有多个分号分隔的.csv文件:

sample.csv
sample1.csv
...etc.

每个都有两个记录、一个头和数据。
示例sample.csv

record-type-cd;record-creation-dt;product-bank-swift-cd;term-deposit-id;saving-global-servicing-bank-name;product-bank-name;customer-account-iban;customer-id;term-deposit-reference;customer-id;term-deposit-reference;payin-iban;payout-iban
ACC;2023-08-18;BBLUK;ABCDEFG-3;check24toprovide;Testcase;DE335666666666666;ABCDEFG-1;2800123456720890;ABCDEFG-1;2800123456720890;DE66110000007000110910000;BE66110000007000110910100

对于每个文件,我需要根据其数据记录的第一个,第二个和第四个字段重命名每个文件。
对于上面的例子,这将是:
ACC2023-08-18ABCDEFG-3.csv
当我使用下面的代码时,它将delimiter__.csv作为新名称:

@echo off
setlocal enabledelayedexpansion

REM Specify the input .csv file name and path
set "inputFile=sample.csv"

REM Read the 2nd line of the .csv file
set /a lineNumber=0
for /f "usebackq skip=1 delims=" %%a in ("%inputFile%") do (
    set /a lineNumber+=1
    if !lineNumber! equ 1 (
        set "line=%%a"
        goto processLine
    )
)

:processLine
REM Set the delimiter used in the .csv file
set "delimiter=;"

REM Split the line into separate columns
set "colIndex=0"
for %%b in ("%line:%delimiter%=" "%") do (
    set /a colIndex+=1
    set "col!colIndex!=%%~b"
)

REM Get the required columns from the line
set "newFileName=!col1!_!col2!_!col4!.csv"

REM Rename the input file
ren "%inputFile%" "!newFileName!"

echo File renamed to: !newFileName!
pause
1szpjjfi

1szpjjfi1#

可用于此任务:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
(for /F "eol=| delims=" %%B in ('dir *.csv /A-D /B 2^>nul') do call :ReadData "%%B") & goto EndBatch
:ReadData
for /F "usebackq skip=1 tokens=1,2,4 delims=;" %%G in (%1) do set "NewFileName=%%G%%H%%I.csv" & goto RenameFile
:RenameFile
if /I not %1 == "%NewFileName%" ren %1 "%NewFileName%"
goto :EOF
:EndBatch
endlocal

前两个命令行使用

  • 关闭命令回波模式,
  • 启用FOR循环、IF条件和goto :EOF所需的命令扩展,
  • 禁用延迟变量扩展以处理文件名中包含!的正确CSV文件。

在后台执行下一个:%ComSpec% /c dir *.csv /A-D /B 2>nul
已启动的%SystemRoot%\System32\cmd.exe运行其内部命令 *,

  • 由于选项/A-D(属性不是目录),仅在当前目录中搜索文件
  • 其中长或短文件名由通配符模式*.csv匹配
  • 并由于选项/B而仅以裸格式输出CSV文件名。

使用2>nul将不包含CSV文件的当前目录上的错误消息输出重定向到设备NUL,从而抑制该错误消息输出。重定向运算符>必须在批处理文件的FOR命令行中转义,才能被cmd.exe解释为文字字符,而不是重定向运算符。
处理批处理文件的 Windows Command Processor 示例捕获在后台执行的命令进程的输出,FOR在启动cmd.exe完成并自行关闭后处理捕获的行。捕获的输出是现在加载到cmd.exe内存中的文件名列表,该内存正在处理批处理文件。
在进行文件重命名之前,将CSV文件的所有文件名都加载到命令进程的内存中非常重要,因为否则可能会发生像for %%B in (*.csv) do这样的简单循环,一些CSV文件根本不被处理,而其他文件则被多次处理。标准的FOR循环在每次迭代时指示文件系统返回下一个与重复模式匹配的文件名,这在重命名同一目录中的文件时是有问题的,因为在每次执行命令REN后,*.csv匹配的文件系统中的文件名列表会发生变化。
使用FOR /F选项eol=|delims=将CSV文件在文件名开头的默认行尾字符;更改为任何文件名都不能包含的垂直行,并将分隔符列表从默认水平制表符和正常空格更改为空分隔符列表。这两个选项确保不会忽略任何CSV文件名以进行进一步处理,并将完整的文件名分配给循环变量B,即使是类似; sample file with leading space and semicolon.csv的文件。
对于每个文件名,调用子例程ReadData,并将文件名传递给"中包含的子例程,以处理包含空格或这些字符之一的正确文件名&()[]{}^=;!'+,~。 整个**FOR**循环包含在命令块中,以行开头的(开始,以"%%B"之后的匹配)结束,用于在同一命令行上使用无条件命令运算符&,并在同一命令行上指定goto EndBatch,以便在使用标签为EndBatch。这避免了在重命名所有CSV文件后进入子例程。 使用子例程重命名数百甚至数千个CSV文件是非常低效的。但是批处理文件的处理通过使用的代码进行了一点优化,因为标签ReadData总是在批处理文件的下一行立即被cmd.exe发现。这减少了文件重命名任务的文件系统访问。 在子例程ReadData中使用了一个**FOR /F**循环,它打开CSV文件,跳过CSV文件顶部的标题行,读取第二行,使用分号作为分隔符将其拆分为子字符串,并将第一个,第二个和第四个分号分隔的字符串分配给循环变量GHI`。

注1:_第二行不能以分号开始,即在第一数据列中具有空值。
注2:_第二行也不应该有空的第二、第三或第四个数据值,因为FOR /F;;解释为一个分隔符,而不是两个分隔符。

换句话说,第二个数据行必须始终具有前四个数据列的四个非空值。
使用第一、第二和第四数据值的CSV文件的新文件名被分配给环境变量NewFileName,并且通过在相同命令行上在无条件命令操作符&之后附加使用用于退出循环的命令goto RenameFile来退出CSV文件的处理,即使CSV文件具有多于两行。这也会导致关闭cmd.exe打开的CSV文件,这在这里很重要,因为CSV文件应该用下一个命令行重命名,这在任何进程(包括处理批处理文件的cmd.exe)仍然打开时都是不可能的。

在以(开始并以匹配的)结束的命令块中,标签是不可能的,这就是使用子例程的原因,在该子例程上,goto RenameFile可以用于退出循环并继续批处理文件,标签RenameFile下面的行。
如果当前CSV文件还没有所需的文件名,则接下来使用不区分大小写的字符串比较进行检查。这种情况使得可以在同一目录中多次运行批处理文件,而不会在当前目录中的一个或多个CSV文件上显示错误消息,这些文件已经具有所需的文件名。
否则,当前CSV文件将重命名为当前文件名不等于新文件名的新名称。如果当前CSV文件被另一个进程打开,或者当前目录中已有与当前文件的新文件名同名的文件/文件夹,则文件重命名可能失败。在这种情况下会输出一条错误消息。
使用goto :EOF退出子例程,导致批处理文件处理返回到第一个FOR /F循环,该循环处理下一个捕获的行或CSV文件名。
要了解所使用的命令及其工作方式,请打开command prompt窗口,在那里执行以下命令,并仔细阅读显示的每个命令的帮助页面。

  • dir /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • ren /?
  • setlocal /?

另请参阅:

相关问题