Eu tenho vários .csv
arquivos delimitados por ponto e vírgula:
sample.csv
sample1.csv
...etc.
Cada um tem dois registros, um cabeçalho e dados.
Exemplo 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
Para cada arquivo, preciso renomear cada arquivo de acordo com o primeiro, segundo e quarto campos de seu registro de dados.
Para o exemplo acima, seria:
ACC2023-08-18ABCDEFG-3.csv
Quando eu uso o seguinte código ele dá delimiter__.csv
como novo nome:
@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
Pode ser usado para esta tarefa:
As duas primeiras linhas de comando definem completamente o ambiente de execução necessário com
goto :EOF
,!
o nome do arquivo.A seguir é executado em segundo plano:
%ComSpec% /c dir *.csv /A-D /B 2>nul
O iniciado
%SystemRoot%\System32\cmd.exe
executa seu comando interno DIR para/A-D
(atributo não diretório)*.csv
/B
.A saída da mensagem de erro no diretório atual que não contém nenhum arquivo CSV é suprimida, redirecionando-a para o dispositivo NUL usando
2>nul
. O operador de redirecionamento>
deve ter escape na linha de comando FOR no arquivo em lote para ser interpretado como caractere literal e não como operador de redirecionamento aocmd.exe
processar o arquivo em lote.A instância do Processador de Comandos do Windows que processa o arquivo em lote captura a saída do processo de comando executado em segundo plano e o FOR processa as linhas capturadas depois de iniciadas
cmd.exe
e encerradas. A saída capturada é uma lista de nomes de arquivos carregados agora na memória docmd.exe
processamento do arquivo em lote.É importante aqui ter todos os nomes de arquivo dos arquivos CSV já carregados na memória do processo de comando antes de renomear os arquivos, caso contrário, pode acontecer com um loop simples como alguns arquivos CSV não são processados e outros são
for %%B in (*.csv) do
processados várias vezes. O loop FOR padrão instrui em cada iteração o sistema de arquivos a retornar o próximo nome de arquivo correspondente ao padrão curinga que é problemático ao renomear arquivos no mesmo diretório que a lista de nomes de arquivos no sistema de arquivos correspondidos por alterações após cada execução do*.csv
comando REN .São usadas as opções FOR /F
eol=|
edelims=
para alterar o caractere padrão de fim de linha;
que um arquivo CSV pode ter no início do nome do arquivo para uma linha vertical que nenhum nome de arquivo pode conter e a lista de delimitadores da guia horizontal padrão e normal espaço para uma lista vazia de delimitadores. Essas duas opções garantem que nenhum nome de arquivo CSV seja ignorado para processamento adicional e que o nome completo do arquivo seja atribuído à variável de loopB
, mesmo que seja algo como; sample file with leading space and semicolon.csv
.Para cada nome de arquivo é chamada a sub-rotina
ReadData
passando o nome do arquivo para a sub-rotina incluída"
para processar também nomes de arquivos corretos contendo um espaço ou um desses caracteres&()[]{}^=;!'+,`~
.Todo o loop FOR é colocado em um bloco de comando começando no
(
início da linha e terminando com a correspondência)
após"%%B"
usar na mesma linha de comando o operador de comando incondicional&
e especificar na mesma linha de comandogoto EndBatch
para continuar o processamento do arquivo em lote após renomear todos os arquivos CSV abaixo da linha com o rótuloEndBatch
. Isso evita cair na sub-rotina após renomear todos os arquivos CSV.É muito ineficiente renomear centenas ou até milhares de arquivos CSV usando uma sub-rotina. Mas o processamento do arquivo de lote é otimizado um pouco com o código usado, pois o rótulo
ReadData
é encontradocmd.exe
sempre imediatamente na próxima linha do arquivo de lote. Isso reduz os acessos ao sistema de arquivos para a tarefa de renomeação de arquivos.Na sub-rotina
ReadData
é usado mais um loop FOR /F que abre o arquivo CSV, pula a linha do cabeçalho no topo do arquivo CSV, lê a segunda linha, divide-a em substrings usando o ponto e vírgula como separador e atribuindo a primeira, segunda e quarto strings separados por ponto e vírgula para as variáveis de loopG
eH
.I
Nota 1: _ A segunda linha nunca deve começar com um ponto e vírgula, ou seja, ter um valor vazio na primeira coluna de dados.
Nota 2: _ A segunda linha nunca deve ter um segundo, terceiro ou quarto valor de dados vazio também porque FOR /F interpreta
;;
como um delimitador e não como dois delimitadores.Em outras palavras, a segunda linha de dados deve ter sempre quatro valores não vazios para as primeiras quatro colunas de dados.
O novo nome de arquivo para o arquivo CSV usando o primeiro, segundo e quarto valor de dados é atribuído à variável de ambiente
NewFileName
e o processamento do arquivo CSV é encerrado usando a mesma linha de comando adicionalmente após o operador de comando incondicional&
o comandogoto RenameFile
para sair do loop mesmo que o arquivo CSV tenha mais de duas linhas. Isso também resulta no fechamento do arquivo CSV aberto, ocmd.exe
que é importante aqui, pois o arquivo CSV deve ser renomeado com a próxima linha de comando, o que não é possível se ainda estiver aberto por qualquer processo, incluindo ocmd.exe
processamento do arquivo em lote.Um rótulo não é possível dentro de um bloco de comando começando
(
e terminando com correspondência)
, que é o motivo para usar uma sub-rotina na qualgoto RenameFile
pode ser usada para sair do loop e continuar o processamento do arquivo em lote com a linha abaixo do rótuloRenameFile
.Em seguida, é verificado com uma comparação de cadeia de caracteres que não diferencia maiúsculas de minúsculas se o arquivo CSV atual ainda não tiver o nome de arquivo desejado. Essa condição possibilita executar o arquivo em lote várias vezes no mesmo diretório sem obter uma mensagem de erro exibida em um ou mais arquivos CSV no diretório atual que já possuem o nome de arquivo desejado.
Caso contrário, o arquivo CSV atual será renomeado para seu novo nome no nome do arquivo atual, sendo diferente do novo nome do arquivo. A renomeação do arquivo pode falhar se o arquivo CSV atual for aberto por outro processo ou se já houver um arquivo/pasta com o mesmo nome que o novo nome de arquivo deve ser para o arquivo atual no diretório atual. É emitida uma mensagem de erro neste caso.
A sub-rotina é encerrada
goto :EOF
resultando no retorno do processamento do arquivo em lote para o primeiro loop FOR /F que processa a próxima linha capturada, respectivamente, o nome do arquivo CSV.Para entender os comandos usados e como eles funcionam, abra uma janela de prompt de comando , execute os seguintes comandos e leia as páginas de ajuda exibidas para cada comando, completa e cuidadosamente.
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
ren /?
setlocal /?
Veja também: