I have already done some research and I have a basic notion but I wonder if anyone could clarify what this expression does and how it does.
...copy more recent files from one directory to another. But besides being the latest (creation date) I have other conditions for copying:
Start with "Financial Report"
Files with the same name in different formats, one in . PDF another in . XLSX.
- Items 10. and 11. [move only 1 pair of files (1 .pdf + 1 .xlsx) per run]:
..but I would like to copy only the most recent pair...
1. Execution of the command Dir /B /A-D /O-D
will result in the listing of items in the current folder, where this output will return only the filenames in a form "basic", a simple nome-de-arquivo.extensão
and also not listing the drive:\caminho\completo\para\nome-de-arquivo.extensão
Dir // lista arquvivos e pastas no Diretorio atual
Dir /B // lista arquvivos e pastas na forma Básica, sem drive/caminho completo
Dir /A-D // lista arquivos apenas, por excluir os itens com Atributo de Diretório,
// observe que o "-" significa exclir o item, como em:
/A-D <==> -Diretórios <==> liste os itens, menos com Atributo -Diretórios
/A-A <==> -Arquivos <==> liste os itens, menos com Atributo -Arquivos
// observe que sem o "-" significa restringir/limitar ao item, como em:
/AD <==> Diretórios <==> liste os itens com Atributo Diretórios
/AA <==> Arquivos <==> liste os itens com Atributo Arquivos
Dir /O-D // lista arquivos em uma dada Ordem, nesse caso, por Data
// observe que o "-" aqui vai significar uma inversão da ordenação padrão:
/OD <==> Ordenar por Data <==> liste do mais antigo para o mais recente/novo
/O-D <==> Ordenar por Data <==> liste do mais recente/novo para o mais antigo
Dir/B/A-D/O-D // liste os nome de arquivos, exclindo os caminho/pastas, na ordem
// inversa, por data de modificação/data de criação (o que for mais recente).
> Dir /B /A-D /O-D
Q99999.txt
A99999.txt
Q99999.cmd
I99999.png
2. The redirect made by the operator "|"
out of command dir
is handled in command Findstr
, and this will result in a listing N
moistened from all lines resulting from the execution of the previous command, dir
.
Dir/B/A-D/O-D // liste arquivos na ordem inversa de data de modificação/criação (mais recente).
^ // o escaping para o uso do pipe "|", que é necessário no for/f ('^|')
| // redireciona a saída do comando anterior (Dir/B/A-D/O-D) para o Findstr
Findstr /N "^" // vai listar a saída obtida no comando anterior, Númerando todas as linhas.
> Dir /B /A-D /O-D | Findstr /N "^"
1:Q99999.txt
2:A99999.txt
3:Q99999.cmd
4:I99999.png
3. The command For /F
loop will create a loop to manipulate the actions resulting from the commands Dir/B..| Findstr..
, capturing the output to make use of these separating them in a predefined way, to meet in its delimiter (delims=:
) defined, and the elements of the first occurrences (tokens= [1]
), and all (*
) the elements of the second occurrence until last occurrence (tokens=1-[*]
).
- For any element/string that appears before the delimiter "
:
" (in the first occurrence of the delimiter), will be treated in the loop variable %%A
, and all occurrences after the first occurrence, ie all occurrences/strings after %%A
, will be treated in the loop variable %%B
[ comando em loop] [ sáida em loop ]
Dir /B /A-D /O-D | Findstr /N "^" 1:Q99999.txt
<elemento %%A > [delimitador] <elemento(s) %%B>
1 : Q99999.txt
2 : A99999.txt
3 : Q99999.cmd
4 : I99999.png
4. To explain the actions of this batch/batch code, I will remove (explaining), which is not necessary (or dispensable):
@Echo off
Set "Xnewest=2" // define uma variavél atribuindo o numero 2 como valor
For /F "tokens=1* delims=:" %%A in (
'Dir /B /A-D /O-D ^| Findstr /N "^"'
) Do If %%A Leq %Xnewest% echo Move "%%B" "X:\Path\to\dest\"
// 2 ecoe Move "%%B" "X:\Path\to\dest\"
// 2 imprima na tela Move "%%B" "X:\Path\to\dest\"
- For each item obtained from the outputs resulting from the listing of the control
Dir..| Findstr
, take %%A
, which is the number that has been assigned to the current command output line Dir
for Findstr
, and if that line number is equal Equ
or less Lss
(Equ
[or] Lss
<==> Leq
), echo/print the command Move..
.
- The command
echo Move..
will only allow a check of the output of the processed loop, so that the author of the code, or the author of the question, has the possibility to check whether the files where the command actually occurs, satisfies the condition in the proposed objective, where it is observed that:
[Dir] Liste arquivos dos mais recentes aos mais antigos e apenas nomes
[Findstr] Enumere as linhas dessa saída, na forma, "numero" + ":" + "nome.extensão"
[For + if (%%A ≦ 2)] Se número da linha é menor ou igual a 2, mova item %%B para drive:\pasta\
5. Components that must satisfy/observe to make this loop/bat effective:
- the bat is running in the same folder where the files are being "manipulated" in loop
- the running bat is either older or has its modification/editing prior to the loop files
6. Considering the utility/application of the commented code, and making a suggestion to limit its action in only the two files .pdf
, and .xlsx
more recent, with the name starting in "Financial Report":
@echo off && cd/d "z:\Pasta\de\Origem\"
for %%i in (xlsx pdf)do for /F tokens^=1*delims^=: %%A in (
'dir/b/a-d/o-d .\"Relat?rio Financeiro*.%%~i"^|findstr/n .
')do if %%~A leq 2 echo=move /y ".\%%~B" "x:\Pasta\de\Destino\."
- Same code/result in version with conventional layout:
@echo off
cd /d "F:\Pasta\Origem"
for %%i in (xlsx,pdf) do (
for /F "tokens=1* delims=:" %%A in ('dir /b /a:-d /o:-d .\"Relat?rio Financeiro*.%%~i" ^| findstr /n .') do (
if %%~A leq 2 echo=move /y ".\%%~B" "X:\Pasta\de\Destino\."
)
)
7. In the suggested item 6., I’m replicating the command echo
enabling the execution in tests/checks, after that, just remove the echo=
for the effective movement of files.
@echo off && cd/d "z:\Pasta\de\Origem\"
for %%i in (xlsx pdf)do for /F tokens^=1*^delims^=: %%A in (
'dir/b/a-d/o-d .\"Relat?rio Financeiro*.%%~i"^|findstr/n .
')do if %%~A leq 2 move /y ".\%%~B" "x:\Pasta\de\Destino\."
- Same code/result in version with conventional layout:
@echo off
cd /d "F:\Pasta\Origem"
for %%i in (xlsx,pdf) do (
for /F "tokens=1* delims=:" %%A in ('dir /b /a:-d /o:-d .\"Relat?rio Financeiro*.%%~i" ^| findstr /n .') do (
if %%~A leq 2 move /y ".\%%~B" "X:\Pasta\de\Destino\."
)
)
8. To move files with the same names and different extensions, applying the order by modification/creation date (whichever is more recent), applying to the files .pdf
and also mesmos_nome.xlsx
:
@echo off && cd/d "z:\Pasta\de\Origem\"
for /F tokens^=1*delims^=: %%A in ('dir/b/a-d/o-d/tc .\"Relat?rio Financeiro*.xlsx"^|findstr/n .
')do if %%~A leq 2 for %%i in (.pdf,%%~xB)do move /y ".\%%~nB%%~i" "x:\Pasta\de\Destino\."
- Same code/result in version with conventional layout:
@echo off
cd /d "z:\Pasta\de\Origem\"
for /f "tokens=1* delims=:" %%A in ('dir /b /a:-d /o:-d /t:c .\"Relat?rio Financeiro*.xlsx" ^| findstr /n .') do (
if %%~A leq 2 for %%i in (.pdf,%%~xB) do move /y ".\%%~nB%%~i" "x:\Pasta\de\Destino\."
)
9. To apply the results only to files where the listing is in order of creation date (no modification), just add /TC
@echo off && cd/d "z:\Pasta\de\Origem\"
for /F tokens^=1*delims^=: %%A in ('dir/b/a-d//o-d/tc .\"Relat?rio Financeiro*.xlsx"^|findstr/n .
')do if %%~A leq 2 for %%i in (.pdf,%%~xB)do move /y ".\%%~nB%%~i" "x:\Pasta\de\Destino\."
- Same code/result in version with conventional layout:
@echo off
cd /d "z:\Pasta\de\Origem\"
for /f "tokens=1* delims=:" %%A in ('dir /b /a:-d /t:c .\"Relat?rio Financeiro*.xlsx" ^| findstr /n .') do (
if %%~A leq 2 for %%i in (.pdf,%%~xB) do move /y ".\%%~nB%%~i" "x:\Pasta\de\Destino\."
)
10. To get the latest file, whether it is this one .pdf
or a .xlsx
, and use the same name for (the most recent file) and move it in "par", (.xlsx + .pdf
or .pdf + .xlsx
) to another folder:
@echo off && cd /d "z:\Pasta\de\Origem\"
for /f tokens^=* %%i in (
'dir/b/a-d/o-d/tc .\"Relat?rio Financeiro*.*"^|%__AppDir__%findstr.exe/eli "\.pdf \.xlsx"')do (
move /y ".\%%~nxi" "x:\Pasta\de\Destino\." && if /i "%%~xi" == ".xlsx" >nul (
move /y ".\%%~ni.xlsx" "x:\Pasta\de\Destino\." ) else >nul (
move /y ".\%%~ni.pdf" "x:\Pasta\de\Destino\.")
) & goto :eOf
Dir/B/A-D/O-D/TC // liste arquivos na ordem inversa de data (criação)
^ // o escaping para o uso do pipe "|", que é necessário no for/f ('^|')
| // redireciona a saída do comando anterior (Dir/B/A-D/O-D/T:C) para o Findstr
Findstr/ELI // obtem no comando anterior, arquivos que terminam (End) Literalmente Insensitivo
"\.pdf \.xlsx" // obtem as linhas que terminarem Literalmente com ".pdf" ou ".xlsx" caso
// Lnsensitivo (independente de caixa alta ou baixa)
// observe que o "\." é diferente de ".", onde sem o uso do "escape" \, vai
// significar para o Findstr "qualquer caratere", mas já o \. vai sinalizar
// Literalmente "." o ponto, assim resultando nas extensões "."+pdf e/ou ".xlsx"
if /i // uso do if em condição de comparação de caso Iinsensitivo
"%%~xi"==".xlsx" // se a eXtensão ("%%~xi") do arquivo em loop for igual ".xlsx", ele move tambémm
// o arquivo com o mesmo Nome + eXtensão ".pdf" par a pasta de destino, caso o
// contrario aconteça, o arquivo ".pdf" é o mais velho dentro do loop, vai
// inverter a ação, movendo primeiro o .pdf, e depois o arquvo de mesmo nome .xlsx
Goto :eOf // como a primeiro laço/loop já foi excutado, o par também já foi movido, e
// entendendo que os outros arquivos do loop não são mais necessários, então
// aborta-se a execução do loop/processamento, movendo a execução do batch
// para o final do arquivo (Goto End Of File)
11. Case in your files, the extension ".pdf
" are always the latest, and need only set the action so that it is based on that extension to get the file name "par" in "xlsx
", or the other way around, by inverting ". pdf"/". xlsx", the sap suggestion:
@echo off
cd/d "z:\Pasta\de\Origem\"
for /f tokens^=* %%i in ('
dir/b/a-d/o-d/tc .\"Relat?rio Financeiro*.pdf"')do >nul (
move /y ".\%%~ni.xlsx" "x:\Pasta\de\Destino\."
move /y ".\%%~nxi" "x:\Pasta\de\Destino\."
goto :eOf
)
Additional explanations about for /f
, skip
, tokens
and delims
:
Some references for consultation/support in /English
:
If the idea is to move only 1 pair of files (1 .pdf + 1 .xlsx) per run, hence the suggestion would be another.
– It Wasn't Me
@Itwasn'tme read your answer and you killed all my doubts regarding expression, I thank you too dear! I didn’t really insert in the question but I would like to copy only the most recent pair, I don’t know if it helps or if it makes a difference edit it, because you have already gone through all the work of writing me your answer, but I am very interested to know your suggestion. I’d need another question?
– Sena
Your question already suggests the action involving the file pair and being recent, and as for the work/time demanded, understand that it is profitable result of isolation period treated as occupational therapy/recreational. ;-)
– It Wasn't Me