0

Disclamer: Previously I needed to compare the date from "last modified" but 5 minutes ago I got a new requirement that I need to compare with the date on the filename as I explain myself bellow.

Imagine that I have 2 folders:

  • C:\FolderData (will be incremented daily with new files)
  • C:\FolderTemp (Needs to have only files from the day before executing, excluding hours/timestamp)

The FolderData will receive filenames that if not for date would be equals, as in:

  1. SYS_PURCHASES_20170617.xls
  2. SYS_PURCHASES_20170618.xls
  3. SYS_PURCHASES_20170619.xls

If I run the .bat file today I need that only the SYS_PURCHASES_20170618.xls be copied over to FolderTemp. That have to be accomplished by getting the last 8 characters from the filename (20170618) and checking if it matches to TODAYDATE - 1.

Is this possible with batch-files and if so, how?

Also accepting answers on Windows PowerShell(6.1) if it also does these steps after:

  1. Copy all files from folder1 to folder2 when the date in the filenames = currentdate - 1;
  2. Remove last 9 digits from all files from folder2 (will remove the date and undescore "_YYYYMMDD") so the file will be SYS_PURCHASES.xls (need to consider every file extension, as there will be .xls, .xlsx and .txt);
  3. Move and replacing the files from folder2 to folder3 (using a simple move /y) - I believe it's possible to do this while doing step 2, no need for a third folder.
mrbTT
  • 1,399
  • 1
  • 18
  • 31
  • 2
    Have you written any code yet? Can you please include it? – sodawillow Jun 19 '17 at 21:10
  • Is the file name part in front of the date always the same? – aschipfl Jun 19 '17 at 23:46
  • @sodawillow, I had something that was replaced by aschipfl provided me as answer at the **DISCLAMER** link. So I would need to replace for something inside the FOR and maintain the DO. – mrbTT Jun 20 '17 at 13:01
  • @aschipfl, no, there will be many names. The files will be generated from legacy systems Daily or sometimes Monthly and the system where it came from and the occurance will be noted at the filename. For instance: `SYS_PURCHASES_D_20170620.txt`, `SYS_PURCHASES_M_20170630.txt`, `SYS_INVESTMENTS_D_20170620.xlsx`, `SYS_MADEUPTHING_D_20170620.xls`. – mrbTT Jun 20 '17 at 13:04
  • Alright... Could there be more files with the same date prefix? – aschipfl Jun 20 '17 at 13:18
  • Do you mean if there could be like 2x `SYS_PURCHASES_D_20170620.txt`? No. But there will be files from other legacy systems with the same date. The full requirement is: **1.** The legacy systems will generate theses files daily/monthly and save them to around 4 different folders (but I considered just 1 for the solution/example, as the folder will be passed as Inputs). **2.** A Job will have to get all files from 2 days prior to another folder and remove the date from the file name. **3.** The new system will load this files into tables, truncating existing date first. – mrbTT Jun 20 '17 at 13:32

3 Answers3

1

As long as the script isn't run on the first of March in a leap year, all files in FolderData with the last digits corresponding to "yesterday" will be

  • Copied to FolderTemp while being stripped from the last 9 digits of the file name
  • Moved to Folder3 while being stripped from the last 9 digits of the file name

My system uses the DDMMYYYY format. Swap the values of the first two variables to set it to MMDDYYYY.

setlocal enabledelayedexpansion


set day=%date:~,2%
set month=%date:~3,2%


set year=%date:~-4%
echo.%day%|findstr /r /b "0">nul&&set day=%day:~1%
echo.%month%|findstr /r /b "0">nul&&set month=%month:~1%
set /a day-=5
if %day% lss 1 (
    set /a day+=30
    set /a month-=1
    if !month!==2 (set /a day-=2
                   set /a leap=year%%4
                   if !leap!==0 set day+=1
    )
    for /l %%# in (1 2 7) do if %month%==%%# set /a day+=1
    for %%# in (8 10 12) do if %month%==%%# set /a day+=1
    if !month!==0 (
        set month=12
        set /a year-=1
    )
)
set day=0%day%
set month=0%month%

for %%# in (C:\FolderData\*) do (
    set name=%%~n#
    if "!name:~-8!"=="%year%%month:~-2%%day:~-2%" (
        copy "%%#" "C:\FolderTemp\!name:~,-9!%%~x#"
    )
)

Please tell me if I misunderstood something.

EDIT: Revised the script to account for going back mutliple days.

Regejok
  • 436
  • 2
  • 5
  • Thanks, I'll be adjusting it to my code and see if it works. The removing last 9 characters only need to be done once. Since the copy is done in the FOR/DO, it doesn't seem to be needed a third folder. The leap year will probably be a problem thou – mrbTT Jun 20 '17 at 13:42
  • Edited my script to account for leap years (modulo of 4 and if 0 it's a leap year). – Regejok Jun 20 '17 at 13:48
  • Hello, the code is nearly perfect, but it isn't working when we're at the start of the month. I changed my PC's date to 20160302, changed the variable to `set /a day-=2` and also moved the `set /a month-=1`up and Am trying to copy files with 20160229. Running the script, the check `if %month%==2 ` is echoing `if 3 == 2`.BTW, neat thing you did to get the months that have 31 days. – mrbTT Jun 20 '17 at 14:36
  • Oh, and also remove the `move /y "%%#" "C:\Folder3\!name:~,-9!%%~x#"` and changed the `copy /y`setting it to `folder3` – mrbTT Jun 20 '17 at 14:51
  • @mrbTT I've edited the script to work with mutliple days before the current date. – Regejok Jun 20 '17 at 15:09
  • Thanks for the help @Regejok, but still having issues when it's supposed to be the month before. (still considering 02 March 2016) Now is crashing between `echo.%month%|findstr /r /b "0">nul&&set month=%month:~1%` and `if %day% lss 1 (` .. Saying **1 was unexpected at this time** BTW, Just realized that since it will be needed to get 2 days prior, what if the `days` variable is -1 – mrbTT Jun 20 '17 at 16:12
  • That is covered with the "lss" , correct? EDIT: Hey I fixed it, moved the `set /a day-=2`after `echo.%month%|findstr /r /b "0">nul&&set month=%month:~1%` and it worked. Could you edit your answer so I can accept it? (also remove the line `move /y "%%#" "C:\Folder3\!name:~,-9!%%~x#"`) – mrbTT Jun 20 '17 at 16:17
  • @mrbTT Stupid mistake on my side: I moved the variable up to make it easier, which causes problems with the arithmetic operation. Negative numbers do not cause an issue, because instead of setting it to a fixed value (like in my original script =28), I used `set /a`. LSS covers all cases for days<1. – Regejok Jun 20 '17 at 16:21
1

With the following powershell script folder2 isn't necessary, you didn't name folder3 - so adjust to your environment.

$Folder1 = "C:\Test\2017\06\20"
$Folder3 = "C:\Test\2017\06\20\Destination"

$YesterDay = (Get-Date).AddDays(-1).ToString('yyyyMMdd')

Get-ChildItem -Path $Folder1 -Filter "SYS_PURCHASES_$YesterDay.*"|Where{ !$_.PSisContainer}|
  Copy-Item -Destination {Join-Path $Folder3 (($($_.BaseName) -replace '_\d{8}$')+$_.Extension)} -whatif

Original output of above script only line breaks inserted

PS C:\test\2017\06\20> ls
    Directory: C:\test\2017\06\20

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       06/20/2017     18:13                Destination
-a----       06/20/2017     18:01           1044 SO_44639321.ps1
-a----       06/20/2017     00:56             24 SYS_PURCHASES_20170617.xls
-a----       06/20/2017     00:56             24 SYS_PURCHASES_20170618.xls
-a----       06/20/2017     01:07             24 SYS_PURCHASES_20170619.txt
-a----       06/20/2017     00:56             24 SYS_PURCHASES_20170619.xls

PS C:\test\2017\06\20> .\SO_44639321.ps1
What if: Performing the operation "Copy File" on target 
"Item: C:\Test\2017\06\20\SYS_PURCHASES_20170619.txt Destination: C:\Test\2017\06\20\Destination\SYS_PURCHASES.txt".
What if: Performing the operation "Copy File" on target 
"Item: C:\Test\2017\06\20\SYS_PURCHASES_20170619.xls Destination: C:\Test\2017\06\20\Destination\SYS_PURCHASES.xls".
PS C:\test\2017\06\20> type .\SO_44639321.ps1

If the output looks right on your system remove the -whatif parameter at the end of the last line.

  • Thanks, this is looking like it will work, but I can't hard code the `SYS_PURCHASES_` as there will be files from other systems aswell (i.e. `SYS_BUYS`, `SYS_INVESTMENTS`, `ADM_MADEUP_DIFF_THING` etc. It needs to be a loop for all files considering the date at the end (all will have the same format _YYYYMMDD) – mrbTT Jun 20 '17 at 13:45
  • That's no problem I wanted to select as exact as possible, if the constant in the names is the trailing underscore and date, I can simply replace `SYS_PURCHASES` with an asterisk as a wildcard. (this differs from the requirements in your question) –  Jun 20 '17 at 13:50
  • Hello, Had to remove the `-File` because Windows PowerShell was pointing out it didn't recognize it as a parameter. The files did get copied, but it didn't remover the _YYYYMMDD at the end, trying to fix it. – mrbTT Jun 20 '17 at 14:43
  • -File requires a newer PoSh version, change script with an alternative to exclude directories. –  Jun 20 '17 at 14:51
  • It still isn't removing the last 9 characters (_YYYYMMDD) from the filename while copying. I'm having trouble searching on how to – mrbTT Jun 20 '17 at 14:54
  • My sample output was from a life test here, did you copy and paste the code or retype eventually not exactly? Especially the curly braces around join-path are important. –  Jun 20 '17 at 14:57
  • Copy paste. Only changed the Folders' path to the real ones. – mrbTT Jun 20 '17 at 14:59
  • I'm sorry a small typo caused the malfunction `&` instead of `$` in the replace. Changed –  Jun 20 '17 at 15:09
  • Still no cigar :/ – mrbTT Jun 20 '17 at 15:54
  • What Version is your PowerShell? `$PSVersionTable.PSVersion` –  Jun 20 '17 at 16:18
  • Major: 2, minor:0, Build: -1, Revision -1 (6.1 was the BuildVersion apparently) – mrbTT Jun 20 '17 at 16:23
  • I ran the above script in Version 2 mode without problems. Sorry I've no clue what the problem is. –  Jun 20 '17 at 16:30
  • I'll try figuring it out, but thanks a lot for your input, I'll give it a point because I believe it's really close! On a solution above RegeJokmanaged to get it working using Batch! :) – mrbTT Jun 20 '17 at 16:36
0

A combined Batch/PowerShell approach.

Powershell for the date calculation and pure batch for the rest

@Echo Off&Setlocal EnableDelayedExpansion
Set "Folder1=C:\Test\2017\06\20"
Set "Folder3=C:\Test\2017\06\20\Destination"

For /f "usebackq delims=" %%A in (
  `Powershell -NonI -Nop -Com "(Get-Date).AddDays(-1).ToString('yyyyMMdd')"`
) Do Set YesterDay=%%A

For /F "Delims=" %%A in (
  'Dir /B/A-D "%Folder1%\*_%YesterDay%.*" '
) Do (
  Set "File=%%~nA"
  Set "File=!File:_%YesterDay%=!"
  Echo Copy "%%~fA" "%Folder3%\!File!%%~xA"
)

Sample output

> SO_44639321.cmd
Copy "C:\Test\2017\06\20\SYS_PURCHASES_20170619.txt" "C:\Test\2017\06\20\Destination\SYS_PURCHASES.txt"
Copy "C:\Test\2017\06\20\SYS_PURCHASES_20170619.xls" "C:\Test\2017\06\20\Destination\SYS_PURCHASES.xls"

If the output looks OK remove the echo in front of copy.