-3

I am having a problem with particular device where i transfer files to. This device is not capable of sorting files for use, it always uses ascending a-z sorting. That creates a problem where i need files to be "processed" by creation date instead.

That said, I came up with an idea to have script in form of .bat file i.e. I would put that script into directory where all the files are and simply run it.

The idea is that script would need to iterate over all the files, the only requirement would be that it needs to sort files descending by creation date before it starts. Then during iteration it would need to rename each file for the purpose of adding letters and digits in front.

The result would be following:

a1-file-name.dat // created 5 min ago
...
a2-file-name.dat // created 10 min ago
...
a9-file-name.dat // created 15 min ago
b1-file-name.dat // created 20 min ago
...
b6-file-name.dat // created 25 min ago
...
b9-file-name.dat // created 30 min ago

I have zero experience and know-how in case of windows scripts, so i would ask for help with this one.

Couple of facts:

  • I can only add up to 6 characters to every file name
  • I cannot add 0 digit to a file name
Mevia
  • 1,223
  • 1
  • 11
  • 36
  • See `for /?` `xcopy /?` and `ren /?` – Nico Nekoru May 23 '20 at 07:23
  • 1
    It would be easier to do this in powershell so check that too ;) – Nico Nekoru May 23 '20 at 07:25
  • yes i just really never had anything to do with windows scripting so its hard to get into it. – Mevia May 23 '20 at 07:31
  • no, `dir /a-d /b /o-d` does the sorting. you just have to add a [`FOR`](https://ss64.com/nt/for.html) loop. it's not that hard – HaxAddict1337 May 23 '20 at 08:19
  • 1
    What is the device? What is its filesystem? My general advice would be to rename/prepend the files with the 'created' date in sortable format, i.e. `YYYY?mm?DD`. No need to try to work out which letters and number combinations have been applied to the existing contents first. If more than one file can be created on the same day, just suffix the date string with the time. – Compo May 23 '20 at 11:08
  • at the beginning i was thinking to this approach, but there is possibility that files will be produced with 1 day delay or 20 ms delay. In this case i would need to use `Year-Month-Day-Hour-Minute-Second-Millisecond` prefix. This is a problem due to limit of characters that can be used for file names. Thats why i came up with a-z1-9 which uses only 2 at all times and date is already on the file. – Mevia May 23 '20 at 11:44
  • Well I have no idea how long your filenames are, @Mevia, or what the filesystem is, but nothing in your question suggested filenames of around 256 characters on an NTFS system, _(and of course there's no need to further increase that by adding `-` characters in between each of the date and time components)_. If you meant by limited characters, the possible `/` in your date, and `:` in your time. those can easily be omitted too. – Compo May 23 '20 at 12:16

2 Answers2

1

Note: My first attempt was COMPLETELY wrong (see comments)

DIR combined with a FOR loop does the job
No, it can't handle characters like !. In this case, a temp file is required:

@echo off
====SETLOCAL EnableExtensions EnableDelayedExpansion


::Clear env
set "letters="
set "numbers="
set/a"#=#lines=posL=posN=0"
set "source="
set "tempFile=%TEMP%\getFiles.tmp"


::A-Z ASCII 97~122
FOR /L %%A in (97 1 122) do (
    "%ComSpec%"/c exit %%A
    set "letters=!letters!!=ExitCodeAscii!"
)
::1-9
FOR /L %%# in (1 1 9) do set "numbers=!numbers!%%#"


::Count #FILES
(dir /A-D /B /T:C /O-D) 1>"%tempFile%" 2>nul
set "getLines="%__APPDIR__%findstr.exe" /N "^^" "%tempFile%""
FOR /F %%L in ('"!getLines!"') do set/a"#lines+=1"


::Read from STDIN
pushd "%source%" || exit /b
setlocal DisableDelayedExpansion EnableExtensions
<"%tempFile%" (FOR /L %%L in (1 1 %#lines%) do (
    set "file="
    set/p"file="
    set/a^"#+=1,^%=Increase order by 1=%
    posL=(#/10^) %% 26,^%=Get position of # in LETTERS modulo 26=%
    posN=(# %% 9^)-1"%=From 1~9=%
    setlocal EnableDelayedExpansion
    FOR /F "tokens=1-2 delims= " %%A in ("!posL! !posN!") do (
        echo(REN "!file!" "!letters:~%%A,1!!numbers:~%%B,1!-!file!"
    ) %=Delete ECHO( to run for true=%
    endlocal
))


popd
endlocal
====ENDLOCAL


::Anything here...

FOR /L %%A in (97 1 122) loops %%A (ASCII code) from 97 to 122. The read-only dynamic variable =ExitCodeAscii is discussed here. It isn't necessary, but it's more flexible when it comes to complex situations.

dir /a-d /b /o-d Let me try again.

dir /A-D /B /T:C /O-D searches the current directory for files, excluding directories and sort based on creation date.

I used an additional FOR loop because I want to substitute a variable with another which both require delayed expansion.

HaxAddict1337
  • 733
  • 1
  • 2
  • 17
  • 1
    I think that sorting should be `/o:d` for to achieve `descending` one (newest files first, oldest ones later), the only thing is that script prints files with new names but doesnt apply them, how to apply them also? – Mevia May 23 '20 at 09:47
  • @Mevia add `REN "%%F" "!letters:~%%N,1!!#:~-1!-%%F"` to the loop – HaxAddict1337 May 23 '20 at 10:05
  • 1
    yes this indeed does work almost perfectly, one last question i have, because with `a` letter digits start at `1` while with every next letter it starts from `0`. Is it possible to make them start from `1` as well? – Mevia May 23 '20 at 10:13
  • oh, i completely forgot about that! will fix it... – HaxAddict1337 May 23 '20 at 10:14
  • 1
    FYI, in order to meet the stated requirements of the question, you should really be using `DIR`'s `/T` option with `C` for created. This statement is incorrect '`dir /a-d /b /o-d` searches the current directory for files, excluding directories and sort based on creation date'. As for the increments, no attention was given to the fact that a variable named `#` is being used. There is no check if one already existed or whether it contained an integer or a string, and no defined value for it at the outset. – Compo May 23 '20 at 11:23
  • @Compo true, all fixed. – HaxAddict1337 May 23 '20 at 13:52
  • 1
    How does it work? Where do I put the source folder? – Ricardo Bohner May 23 '20 at 17:13
  • @RicardoBohner i forgot about that. i edited, please read the answer again – HaxAddict1337 May 23 '20 at 22:26
1

You could use something like this code. The only problem is if the source Folder has more than 234 files cause thats all [a-z][1-9] allows 26 * 9 = 234 possibilities. My Video.

@echo off
SetLocal EnableDelayedExpansion
set Source=%userprofile%\desktop\Test
set Letters=abcdefghijklmnopqrstuvwxyz
set Numbers=123456789
set /a CountL=0
set /a CountN=0

for /f "Delims=" %%a in ('dir /b /o-d /tc /s /a-d "%Source%"') do (
set /a TCounter+=1
set FileName=%%~nxa
set FullPath=%%~fa
Call :Rename
set /a CountN+=1
if !CountN! EQU 9 set /a CountN=0& set /a CountL+=1
if !TCounter! EQU 234 goto :Exit
)
:Exit
exit
:Rename
ren "!Fullpath!" "!Letters:~%CountL%,1!!Numbers:~%CountN%,1!!FileName!"
goto :EOF

This is the [a-z][a-z][1-9][1-9]filename.ext version:

@echo off
SetLocal EnableDelayedExpansion
set Source=%userprofile%\desktop\Test
set Letters=abcdefghijklmnopqrstuvwxyz
set Numbers=123456789
set /a CountL=0
set /a CountN=0
set /a CountL2=0
set /a CountN2=0

for /f "Delims=" %%a in ('dir /b /o-d /tc /s /a-d "%Source%"') do (

set FileName=%%~nxa
set FullPath=%%~fa
Call :Rename
set /a CountN2+=1
if !CountN2! EQU 9 set /a CountN2=0& set /a CountN+=1
IF !CountN! EQU 9 set /a CountN=0& set /a CountN2=0& set /a CountL2+=1
IF !CountL2! EQU 26 set /a CountL+=1
)
:Exit
exit
:Rename
ren "!Fullpath!" "!Letters:~%CountL%,1!!Letters:~%CountL2%,1!!Numbers:~%CountN%,1!!Numbers:~%CountN2%,1!!FileName!"
goto :EOF
Ricardo Bohner
  • 217
  • 2
  • 8
  • 1
    You can have `Set "FullPath=%%a"` because the `/S` option with `Dir` will output the full paths anyhow! – Compo May 23 '20 at 12:22
  • Yeah, true could also be "FullPath=%%a" – Ricardo Bohner May 23 '20 at 12:26
  • In addition, this doesn't appear to adjust the leading letter according to the five minute increments stipulated in the question. No attempt has been made to parse any of the created dates or times or even to sort the `Dir` output according to the created timestamps. – Compo May 23 '20 at 12:29
  • for some reason it does not work for me, i am getting "cannot find file" n amount of times, for every file in directory (even though i have set up the Test directory matching the example `C:\Users\MY_NAME\Desktop\Test`, files are in the Test dir) – Mevia May 23 '20 at 12:30
  • I forgot to include order by date but now fixed and I also included something to stop the script if there are more than 234 files in the directory so the rest of the files will not be renamed – Ricardo Bohner May 23 '20 at 12:34
  • i think that this script assumes that file names cannot have spaces like `unit891w [krc] faults-no.dat`, how can this be patched? – Mevia May 23 '20 at 12:38
  • 1
    Just an observation, but if there could only be `234` files in the directory, would it not make more sense to just prepend the filenames with three integers `001` - `999` to allow for 765 more files, or lets say `0001` - `9999` to allow for 9765 more files etc. – Compo May 23 '20 at 12:38
  • @Compo, i have said multiple times that this is the only way it can be done. The device files are sent to, is piece of machine that operates in the factory and has its own os and limitations. for example i am allowed to add max 6 characters to every file. Machine also doesnt recognise `0` so if you put 0 it will throw error. Then 11 is processed before 1 for some reason. So i have what i have to work with. – Mevia May 23 '20 at 12:40
  • Are you saying @Mevia, that you cannot have filenames containing the character `0`, or do you mean with a leading character `0`? If the latter then why not prepend with `100001` to `999999`? The issue currently is that you've not provided sufficient information about the OS/filesystem of the target machine, or its limitations. This is a technical site, not a guessing one, solutions are provided to specific criteria. We need to know that criteria in your question body, please [edit it](https://stackoverflow.com/posts/61968670/edit) accordingly. – Compo May 23 '20 at 12:45
  • `0` cannot be anywhere in the filename, the machine is not important its also nothing you will find in the internet, its not using any standarized or known os, its like custom made for its job, i analysed what is needed and asked it in the question. btw @Compo thank you for the downvote (i appreciate it) – Mevia May 23 '20 at 12:48
  • I said [edit your question](https://stackoverflow.com/posts/61968670/edit), potential helpers shouldn't need to read all of the comments to pick out important information like this. You must provide all of the the limitations and criteria there, not in the comment section. That should obviously include the number of files, their potential lengths, the file system etc. too! Oh, and BTW, if I downnvote, I almost always tell you that I have and why. As that hasn't happened do not make incorrect assumptions. _(I can understand why somebody has though!)_ – Compo May 23 '20 at 12:51
  • Ok i fixed the problem with spaces in names i forgot the deslims= in the for loop – Ricardo Bohner May 23 '20 at 12:51
  • @Ricardo Bohner this is perfect, exactly what i needed, working nicely, thank you! – Mevia May 23 '20 at 12:58
  • By the way did you want oldest files first or newest files first the current order is oldest files first but if you want to invert just change from dir /b /od /s /a-d "%Source% to dir /b /o-d /s /a-d "%Source% – Ricardo Bohner May 23 '20 at 13:01
  • yes yes i needed newest once first, thank you for the fix – Mevia May 23 '20 at 13:03
  • 1
    In addition to your comment about not having a `0` anywhere in the filename, @Mevia, you stated [here](https://stackoverflow.com/questions/61968670/rename-all-files-in-a-directory-by-adding-a-z1-9-in-front-of-each-file#comment109606920_61968670), that the date was already in the filename, so how does it cope with `2020`, also what happens when the file was created on the tenth, twentieth or thirtieth day of a month? or in the tenth month? what is it using for the date then? Also if the date is in the filename why not just reorder and position it to the beginning of the filename instead? – Compo May 23 '20 at 13:04
  • not on the file name, i said on the file (meaning in the meta data of the file), and that date is only useful if you need to manually check the files while they are still in the PC. After you transfer files to the machine its not possible anymore, machine processes files one by one based on asc a-z, which is a reason this topic started. we need files to be processed from the newest to oldest, but we couldnt put date to the file, so i analysed and came up with solution, everything was said in the question, i only dont know windows scripting so i came for someone to help out with coding part. – Mevia May 23 '20 at 13:08
  • Once again, @Mevia, the question area is for information relevant to your question, not in the comments. Your question is already off topic for being a code request, not assistance with your provided code. It is also off topic for being unclear due to the missing information I've already identified. – Compo May 23 '20 at 13:11
  • 1
    To fix the 237 files limit you could use something like [a-z][a-z][1-9][1-9]MyFile.txt insted of [a-z][1-9]MyFile.txt – Ricardo Bohner May 23 '20 at 13:14
  • @Ricardo Bohner would you be so kind to update your answer with this idea? that would improve this a lot – Mevia May 23 '20 at 13:16
  • …or even more if six characters are allowed to be prepended, `308,915,776` (although you'd probably want to ignore the five minute interval for incrementing the letters, which has already been ignored anyhow!), `aaaaaa` to `zzzzzz`. – Compo May 23 '20 at 13:28
  • As a side note to all of this, @Mevia, because you've stated that there's a maximum limit of six additional characters, the code should have to determine the existing filename lengths, to ensure that the limit isn't reached. Also as no information has been provided, other than the files are transferred to another machine, it may be necessary, to determine whether any of the filenames have already been prepended prior to renaming them. – Compo May 23 '20 at 13:34
  • As mentioned in the comments of the other answer, in order to meet the stated requirements of the question, you should really be using `DIR`'s `/T` option with `C` for 'created', currently it is using the default ordering with `W`, for 'modified'. – Compo May 23 '20 at 13:43
  • I added the [a-z][a-z][1-9][1-9]filename.ext version – Ricardo Bohner May 23 '20 at 14:14
  • @Compo: Thanks, I thought dir /o-d would use "Creation Date" by default, but seems not. – Ricardo Bohner May 23 '20 at 16:54
  • The questions' result box certainly uses the term 'created', not 'modified'. But TBF, it's not really important, because they came here to abuse the site, had no intention of following its guidelines or showing sufficient courtesy to appropriately address the concerns raised in the subsequent comments. _They don't really deserve others to give their time and effort on their behalf_. – Compo May 23 '20 at 17:02
  • @Compo I think that there should be a policy that deal with what you are doing, you actually came here to harass. We perfectly coordinated the issue, answers were posted, topic is closed, while you are still spaming the comments and attacking. I dont think its anything else then harassment. – Mevia May 23 '20 at 18:45
  • @Ricardo Bohner this new answer is working perfectly thank you for the help, its saving us so many time of manual work ;) – Mevia May 23 '20 at 18:46
  • @Mevia, the fact that your question was a code request, didn't follow the guidelines and was voted to be closed by others, is completely down to me harassing you. If you don't like the guidelines for the site, you're free not to sign up to it, and use it. Also, if you've a genuine grievance with my comments, I'm happy to discuss them with you further, but please note, I didn't create the site rules, and have had no part in their implementation or design. Feel free to take the [tour], read [mcve], and all of the links under [ask], to get an insight into their main areas, before you do, thanks. – Compo May 23 '20 at 19:08
  • @OP you can shorten phrases a lot. `set/a"CountL=CountN=CountL2=CountN2=0"` – HaxAddict1337 May 23 '20 at 22:28