'CMD/BAT get date modified of all filenames and append to their filename

I am having trouble with this script. I'll explain below the codeblock.

@Echo off
pushd "\\server\folder"
SETLOCAL EnableDelayedExpansion

@FOR /F "TOKENS=2" %%A IN ('WHERE /T "testfiles*.*"') DO @(
set fdate123=%%A
echo !fdate123:~5,9!0!fdate123:~0,1!!fdate123:~2,2!
call StringLen !fdate123!
)

pause

:StringLen
Setlocal EnableDelayedExpansion
:: strLen String [RtnVar]
::             -- String  The string to be measured, surround in quotes if it contains spaces.
::             -- RtnVar  An optional variable to be used to return the string length.
Set "s=#%~1"
Set "len=0"
For %%N in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
  if "!s:~%%N,1!" neq "" (
    set /a "len+=%%N"
    set "s=!s:~%%N!"
  )
)

Endlocal&if "%~2" neq "" (set %~2=%len%) else echo %len%
Exit /b

What I'm trying to do it get the date modified of the file, and change the format of that date returned to YYYYMMDD. I want the date modified to be appended to the filename. I can have files from multiple days in this folder and each file may have a different date modified date.

Please do not mark this as a duplicate question, because I could not find this approach to doing this here.

I was trying to test for date string length so I can handle dates like 1/1/2019 (length of 8) vs 1/13/2019 (length of 9) vs 10/1/2019 (length of 9) vs 10/22/2019 (length of 10) then using if statements parse the date appropriately with the likes of something like !fdate123:~5,9!!fdate123:~0,1!!fdate123:~2,2! - I have not finished this yet.

I have tried getting the date with dir /T:W testfiles*.* and running a findstr but I don't understand findstr well enough to do that.

I also tried to pull it from forfiles /M BC_Services_Adjustment* /C "cmd /c echo @fdate" and moved on from that as well.

maybe somebody has a better solution, I think mine is a mess right now. Does anybody know how to get the date modified time stamp of every file in a folder, convert it a variable with YYYYMMDD format and then append it into all the files in a folder?

Note: I am not looking for powershell solutions for this question, please do not waste your time posting powershell answers.

Update #2 (5/21/19) I tried magoo's code, I'm still needing a solution to rename the files.

@echo off
pushd "\\server\folder"
SETLOCAL EnableDelayedExpansion

FOR /F "TOKENS=2" %%A IN ('WHERE /T "*.csv"') DO (
     for /f "tokens=1-3delims=/-." %%i in ("%%A") do (
     set "mm=00%%i"&set "dd=00%%j"&set "yy=0000%%k"
     set "fdate123=!yy:~-4!!mm:~-2!!dd:~-2!"
     )
rem echo to test if date modified matches to the right filenames. 
echo !fdate123! ^& %%A
rem ren "%%~nxA" "%%~nxA!fdate123!"
)
pause

I have tried with the ren "%%~nxA" "%%~nxA!fdate123!" but it's not finding the file. Probably super simple. If somebody can make magoo's code do a rename instead of just echoing the date I can award out the bounty on this question.



Solution 1:[1]

I figured this out on my own, pure batch solution. Takes date modified, appends it to any filename in a directory in YYYYMMDD format. I really was overcomplicating it, can't believe I didn't come up with this prior to setting a bounty. lol

pushd "\\server\folder"
SETLOCAL EnableDelayedExpansion
FOR /r %%f IN (*) DO SET filedatetime=%%~tf & ren "%%~nf.*" "%%~nf!filedatetime:~6,4!!filedatetime:~0,2!!filedatetime:~3,2!%%~xf" 

Solution 2:[2]

Be sure to specify your extentions so if your bat file is in that directory, it will not also be renamed.

@echo off pushd "\\server\path123" SETLOCAL EnableDelayedExpansion FOR /r %%f IN (*.csv, *.txt) DO SET filedatetime=%%~tf & ren "%%~nf.*" "%%~nf!filedatetime:~6,4!!filedatetime:~0,2!!filedatetime:~3,2!%%~xf

Solution 3:[3]

FOR /F "TOKENS=2" %%A IN ('WHERE /T "testfiles*.*"') DO (
 for /f "tokens=1-3delims=/-." %%i in ("%%A") do set "mm=00%%i"&set "dd=00%%j"&set "yy=0000%%k"
 set "fdate123=!mm:~-2!!dd:~-2!!yy:~-4!"
 echo !fdate123!
)

should allow you to construct the data according to your wishes.

The inner if assigns mm, dd and yy as appropriate, using the delimiters specified analysing %%A as a literal. Each is prefixed by an appropriate number of zeroes. The required string is then constructed using substringing selecting the last 2/4 characters of the string, so an 8-character output is obtained.

I use dd/mm/yyyy format and haven't actually tested this method, but manipulating it to your requirements should be obvious, the only issue really being how to handle yy dates as distingct from yyyy dates, if that's a concern.

Solution 4:[4]

Yes, I read that you do not want any PowerShell answers. Please be sure not to select this one as the answer. I did not waste my time writing something for you. This is for someone else who might get some benefit.

[CmdletBinding()]
Param (
    [Parameter(Mandatory=$true)]
    [string]$CommandName
)

$dirlist = @('.') + ($Env:Path.Split(';'))
$extensions = @('') + ($Env:PATHEXT.Split(';'))

$results = foreach ($dir in $dirlist) {
    if (($dir) -and ($dir -ne '')) {
        if (Test-Path -Path $dir -ErrorAction SilentlyContinue) {
            # The directory path exists.
            # Check for presence of the file with any executable extension.
            $dirhash = @{}

            foreach ($extension in $extensions) {
                Get-ChildItem -File -Path $dir -Filter "$CommandName$extension" |
                    ForEach-Object {
                        # If the file name is not already in the hash, add it to the hash
                        # and output it in the pipeline.
                        if (-not $dirhash.ContainsKey($_.Name)) {
                            $dirhash.Add($_.Name,1)
                            $_
                        }
                    }
            }
        }
    }
}

$results | ForEach-Object {
    Rename-Item -LiteralPath $_.FullName -NewName ($_.BaseName + $($_.LastWriteTime.ToString('yyyyMMdd')) + $_.Extension)
}

UPDATE:

Now that the OP's intent is known, this is a much more simple problem. Once you are confident the files will be renamed correctly, remove the -WhatIf from the Rename-Item cmdlet.

Set-Location -Path '//server/sharename'

Get-ChildItem -File -Filter 'testfiles*.*' |
    ForEach-Object {
        Rename-Item -LiteralPath $_.FullName -NewName ($_.BaseName + $($_.LastWriteTime.ToString('yyyyMMdd')) + $_.Extension) -WhatIf
    }

Solution 5:[5]

I believe that the output from is in a consistent format, so I would suggest this as a possible single line option:

@PushD "\\server\folder" 2>Nul&&For /F "Tokens=1-4*Delims=/  " %%A In ('RoboCopy . $ testfiles*.* /L /NS /NJS /NJH /NDL /NC /TS')Do @Ren "%%E" "%%A%%B%%C-%%~nxE"

Alternatively, based upon your edited additional example code, this is more likely what you need:

@PushD "\\server\folder" 2>Nul&&For /F "Tokens=1-4*Delims=/  " %%A In ('RoboCopy . $ testfiles*.* /L /NS /NJS /NJH /NDL /NC /TS')Do @Ren "%%E" "testfiles%%A%%B%%C%%~xE"

If each renamed file is run through the for loop again, you may need to expand this from a single line solution to prevent it.

In both code examples, the Delimiters are /TAB                                        

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 shadow2020
Solution 2 Tman1984
Solution 3 Magoo
Solution 4
Solution 5