# Solved: File management



## N2gadgets (Mar 21, 2015)

Hello,
I have tens of thousands of files I need help sorting. Hopefully someone can assist.
All my files are in sets of 3 or 4 files with matching names. Im looking for a batch file that will find all files with a CSV extension then create sub folders based upon the year it was created. I then need those CSV files moved into their creation date folders with any associated files in their set. For example:
HPD00100002222.csv (2014)
HPD00100002222.osg.svg (2010)
HPD00100002222.dsg.svg (2010)
HPD00100002222.jpg (2011)
HPD00100002230.csv (2009)
HPD00100002230.osg.svg (2009
HPD00100002230.dsg.svg (2010)
HPD00100001234.csv (2010)
HPD00100001234.osg.svg (2008)
HPD00100001234.dsg.svg (2009)
HPD00100001234.jpg (2010)
HPD00100004321.csv (2014)
HPD00100004321.osg.svg (2009)
HPD00100004321.dsg.svg (2010)
The batch file would find 4 CSV files. It would then create 3 sub folders based on the file creation date: 2009 2010 and 2014.
It would then move each CSV file into its correct folder along with their matching file sets. (regardless if the matching file sets have different creation dates).
thank you.


----------



## foxidrive (Oct 20, 2012)

Show us a line from running this at a cmd prompt, in the folder with the files. The format is important.

All the files are in one folder, right?


```
for %a in (*.csv) do @echo %~ta
```


----------



## N2gadgets (Mar 21, 2015)

Thank you for the reply. Yes all the files are in one folder called DATA.
I ran the code and got:

~ta was unexpected at this time.


----------



## N2gadgets (Mar 21, 2015)

I did modify it to:
for %%a in (*.csv) do echo %%~ta
and I get a listing of all time date for CSV files. Sample:

03/18/2014 06:58 AM
03/18/2014 07:51 AM
03/18/2014 03:13 PM
03/31/2014 09:02 AM
03/31/2014 09:12 AM
03/31/2014 09:28 AM
03/31/2014 10:05 AM
03/31/2014 10:18 AM
03/31/2014 10:32 AM
03/31/2014 12:40 PM
03/31/2014 02:45 PM


----------



## foxidrive (Oct 20, 2012)

Thanks for the info above - I realised that it's modifed date and not creation date so I took a different tack.
JFTR the command I showed above will work from a cmd prompt.

Run this in a *test folder* of some files and verify that it does what you want before using it on your actual folder.


```
@echo off
:loop
set "file=%temp%\movefile-%random%.vbs"
if exist "%file%" goto :loop


:: change the filespec here

dir "*.csv" /b /a-d >"%file%.list"


(
 echo. Const ForReading = 1, ForWriting = 2
 echo. infile = "%file%.list"
 echo. Set fso = CreateObject("Scripting.FileSystemObject"^)
 echo. Set f1 = fso.OpenTextFile(infile, ForReading^)
 echo. Do While not f1.AtEndOfStream
 echo. Set f = fso.GetFile(f1.readline^)
 echo. ' n = f.DateLastAccessed
 echo.   nc = f.DateCreated
 echo. ' nm = f.DateLastModified
 echo. WScript.Echo CStr(Year(nc^)^)+" "+chr(34^)+f+chr(34^)
 echo. loop
 echo. f1.close
)>"%file%"
cscript //nologo "%file%" >"%file%.txt"

 for /f "usebackq tokens=1,* delims= " %%a in ("%file%.txt") do (
      echo processing year "%%a" and filespec "%%~nb.*"
      md "%%a" 2>nul
      move "%%~nb.*" "%%a" >nul
   )
del "%file%.txt" "%file%.list" "%file%"
pause
```


----------



## N2gadgets (Mar 21, 2015)

Foxidrive, thanks for this...progress is being made!..but it seems its taking all CSV files found and making a 2015 folder then copying all the file sets (except for jpegs) into that 2015 folder regardless of modified date.

Here is a bit from the copy output.:
Output when running script:
processing year "2015" and filespec "HPD0091000136.*"
processing year "2015" and filespec "HPD0091000137.*"
processing year "2015" and filespec "HPD0091000138.*"
processing year "2015" and filespec "HPD0091000139.*"
processing year "2015" and filespec "HPD0091000140.*"
processing year "2015" and filespec "HPD0091000141.*"
processing year "2015" and filespec "HPD0091000142.*"
Press any key to continue . . .
D:\DATA>


Here is a dir to text output that shows the formatting of the JPGs, CSV and SVG file names. I had forgotten it adds the 0001 to the original file name for JPG.

12/04/2014 04:02 PM 4,264 HPD0001002395.csv
12/04/2014 04:01 PM 1,954 HPD0001002395.dsg.svg
03/07/2012 03:43 PM 2,051 HPD0001002395.osg.svg
12/04/2014 04:02 PM 23,950 HPD00010023950001.JPG
02/21/2014 09:40 AM 4,088 HPD0005001622.csv
02/21/2014 09:40 AM 3,297 HPD0005001622.dsg.svg
03/08/2012 11:27 AM 3,357 HPD0005001622.osg.svg
02/21/2014 09:40 AM 32,067 HPD00050016220001.JPG
02/21/2014 02:41 PM 4,137 HPD0005001630.csv
02/21/2014 02:41 PM 3,177 HPD0005001630.dsg.svg
03/08/2012 11:27 AM 3,357 HPD0005001630.osg.svg
02/21/2014 02:41 PM 31,004 HPD00050016300001.JPG


----------



## foxidrive (Oct 20, 2012)

When I tested this I noticed that if the files are copied to another folder then the creation date is changed. 
I was surprised but didn't investigate further.

You did originally say creation date, and not modified date.

Remove these lines and try it on another folder that already exists long term - and you should see that there are different dates.


```
md "%%a" 2>nul
      move "%%~nb.*" "%%a" >nul
```


----------



## DaveBurnett (Nov 11, 2002)

There is an option/parameter to the copy/move option under DOS not to modify the date if I remember correctly.


----------



## foxidrive (Oct 20, 2012)

The filesystem handles the timestamping and there has never been such an option in MSDOS or in NT series Windows.


----------



## DaveBurnett (Nov 11, 2002)

I am thinking of the NTFS last access timestamp.


----------



## Grobu (May 2, 2013)

Hello N2Gadgets

Would the following code meet your needs?


```
@echo off
    
    setlocal
    
    set year=
    set name=
    set prefix=
    set destination=
        
    for /f "eol=  delims=  " %%a in ('dir *.csv /t:w') do (
        for /f "tokens=1,4,*" %%b in ("%%a") do (
            set year=%%b
            set "name=%%d"
            call :prcsLine
            )
        )

    goto end
    
:prcsLine
    for /f "delims=. tokens=1" %%a in ("%name%") do set "prefix=%%a"
    set "destination=%year:~-4%"
    if not exist "%destination%\." mkdir "%destination%"
    move "%name%" "%destination%"
    move "%prefix%.*" "%destination%"
    goto :eof
        
        
:end
```


----------



## N2gadgets (Mar 21, 2015)

Code suggestion:
Yes this worked a treat...however it did not move any of my JPEGs. Everything else looks great....folders created with correct year name, and CSV and SVG files moved to correct folders as well.


----------



## foxidrive (Oct 20, 2012)

Grobu said:


> Hello N2Gadgets
> 
> Would the following code meet your needs?


It has some flaws and limitations Grobu.

The date format is dependent on the computer that is running it, and can fail.
The filename will be wrong and will fail if the time format is not the same as your computer (12/24 hour)
The date it is looking at is the last written and not the creation date, which the question asks for.



foxidrive said:


> Remove these lines and try it on another folder that already exists long term - and you should see that there are different dates.


N2Gadgets, is there a reason you didn't comment on the above?

The creation date is reset to the current date when a file is copied.


----------



## N2gadgets (Mar 21, 2015)

Foxidrive:
My apologies for not responding sooner. Looking back on my request, I see my error in requesting actions based on creation date. My original folder does have the long term files, but I did not want to test on that data, so I copied to a test folder..hence modifing the creation date. I was attempting copy the data into a test folder and retain the original creation date...but then saw Grobu's suggestion and wanted to try that code in the last few minutes at work tonight.
I see now that my files may be copied at some point in the future..but never modified...so basing the code on modified date would be a more prudent choice. Your code is certinly more robust..could it be modified to look at modified date instead?
Thank you for lending your expertise to my issue.


----------



## N2gadgets (Mar 21, 2015)

foxidrive said:


> The filesystem handles the timestamping and there has never been such an option in MSDOS or in NT series Windows.


Yes I found this out....I did see some 3rd party apps that would add extensions in explorer to modify the creation date...but did not appear to do large file batches.
The only other way I saw...was to copy the files to another folder...change the date\time on the computer ..run a small batch file that basically copied the file over itself...thus modifying the creation date. I quickly dismissed this as not a viable option.


----------



## foxidrive (Oct 20, 2012)

It was a minor change to use the modified date - test this script.

*EDIT:* This line was changed to handle the different JPG filenames

move "%%~nb*.*" "%%a" >nul


```
@echo off
:loop
set "file=%temp%\movefile-%random%.vbs"
if exist "%file%" goto :loop


:: change the filespec here

dir "*.csv" /b /a-d >"%file%.list"


(
 echo. Const ForReading = 1, ForWriting = 2
 echo. infile = "%file%.list"
 echo. Set fso = CreateObject("Scripting.FileSystemObject"^)
 echo. Set f1 = fso.OpenTextFile(infile, ForReading^)
 echo. Do While not f1.AtEndOfStream
 echo. Set f = fso.GetFile(f1.readline^)
 echo.   na = f.DateLastAccessed
 echo.   nc = f.DateCreated
 echo.   nm = f.DateLastModified
 echo. WScript.Echo CStr(Year(nm^)^)+" "+chr(34^)+f+chr(34^)
 echo. loop
 echo. f1.close
)>"%file%"
cscript //nologo "%file%" >"%file%.txt"

 for /f "usebackq tokens=1,* delims= " %%a in ("%file%.txt") do (
      echo processing year "%%a" and filespec "%%~nb.*"
      md "%%a" 2>nul
      move "%%~nb*.*" "%%a" >nul
   )
del "%file%.txt" "%file%.list" "%file%"
pause
```


----------



## N2gadgets (Mar 21, 2015)

Thank you, I look forward to testing tomorrow at work. I have a feeling this will be what I need. As a side note I can see you have some great code skills. I would really like to increase my abilities in this area. Are there any books or references that you believe were especially helpful to you?


----------



## foxidrive (Oct 20, 2012)

Learning by changing scripts in minor ways, seeing how things change - on-the-job training is a good way to go.

Timo Salmi's collections will give a good set of offline materials to read and change and learn from, along with the FAQ he's developed.

Batch file resource list 
===============
http://www.dostips.com/forum/
http://www.computerhope.com/forum/index.php/board,2.0.html has a dos section
http://forums.techguy.org/23-dos-other/
http://stackoverflow.com/ has a batch file tag that you can search with
http://ss64.com/
http://www.netikka.net/tsneti/info/tscmd.php Timo Salmi's collection
and there is a ZIP file filled with material http://www.netikka.net/tsneti/pc/link/tscmd.zip


----------



## Grobu (May 2, 2013)

*Foxidrive*


> The filename will be wrong and will fail if the time format is not the same as _your computer_ (12/24 hour)


I didn't take the time format from _my computer_ but from the output of the original poster's. You asked him to perform a for

```
%a in (*.csv) do @echo %~ta
```
which yielded
03/18/2014 06:58 AM​

```
The date it is looking at is the last written and not the creation date, which the question asks for.
```
I referred to the OP's remark :

```
it seems its taking all CSV files found and making a 2015 folder then copying all the file sets (except for jpegs) into that 2015 folder regardless of [B][U]modified date[/U][/B].
```
*N2gadgets*

Sorry about the JPG files, forgot to take into account the "001" appending. Following code should correct that :


```
@echo off
    
    setlocal
    
    set year=
    set name=
    set prefix=
    set destination=
        
    for /f "eol=  delims=  " %%a in ('dir *.csv /n /4 /t:w') do (
        for /f "tokens=1,4,*" %%b in ("%%a") do (
            set year=%%b
            set "name=%%d"
            call :prcsLine
            )
        )

    goto end
    
:prcsLine
    for /f "delims=. tokens=1" %%a in ("%name%") do set "prefix=%%a"
    set "destination=%year:~-4%"
    if not exist "%destination%\." mkdir "%destination%"
    move "%name%" "%destination%"
    move "%prefix%*.*" "%destination%"
    goto :eof
        
        
:end
```
Also, there appears to be command-line utilities for altering a file date/time information :
http://www.funduc.com/fstouch.htm
http://sourceforge.net/projects/touchforwindows/​
Hope that helps!


----------



## foxidrive (Oct 20, 2012)

*EDITED:*



Grobu said:


> Foxidrive
> I didn't take the time format from my computer but from the output of the original poster's. You asked him to perform a for
> 
> ```
> ...


That's fair and a good point.

You made no comments on how it will fail in different ways for other people who wander by in the future - so I had no idea if you realised.



Grobu said:


> I referred to the OP's remark :
> 
> 
> > into that 2015 folder regardless of *modified date*.


I saw that too and I asked about it - the original post said creation date so I went with that.



Grobu said:


> for /f "delims=. tokens=1" %%a in ("%name%") do set "prefix=%%a"


You could use this to replace the line above, to make it more robust and simpler code.

```
set "prefix=%~n1"
```
This is untested, but based on your code this may work too.


```
@echo off
for /f "tokens=3,6,* delims=/ " %%a in ('dir *.csv /t:w 2^>nul ^|find /i ".csv"') do (
         Echo processing year "%%a" and files "%%~nb*.*"
         md "%%a" 2>nul
         move "%%~nb*.*" "%%a" >nul
    )
pause
```
Removing the "echo processing..." line will make it run faster, and the same applies in my solution above.


----------



## foxidrive (Oct 20, 2012)

N2gadgets said:


> Thank you, I look forward to testing tomorrow at work.


No worries, let us know how it goes for your situation.
Take note that the modified code above has been edited to handle the different JPG filenames.


----------



## N2gadgets (Mar 21, 2015)

foxidrive said:


> No worries, let us know how it goes for your situation.
> Take note that the modified code above has been edited to handle the different JPG filenames.


Foxidrive, this works perfectly. All files into their correct folders. I would like to thank you and Grobu for your excellent work. Both scripts now appear to do exactly what I need.
It appears each approaches the issue a bit differently....which is perfect for me. I will be studying the supplied reference materials and be modify each script to see how it changes the outcomes...Absolutely what I need to further my skills.
Thanks again!


----------



## N2gadgets (Mar 21, 2015)

Grobu said:


> *Foxidrive*
> 
> I didn't take the time format from _my computer_ but from the output of the original poster's. You asked him to perform a for
> 
> ...


Grobu,
Yes this does help! Thank you for your help...it is greatly appreciated. Both you and Foxidrive are ACES!
Ill be checking out those links as well just for future reference!
thanks again.


----------



## Grobu (May 2, 2013)

*FoxiDrive*



> Originally Posted by Grobu View Post
> 
> ```
> for /f "delims=. tokens=1" %%a in ("%name%") do set "prefix=%%a"
> ...


Nice, that is certainly more concise and elegant! Only thing to keep in mind is, file name shouldn't have multiple dots.



> This is untested, but based on your code this may work too.
> 
> 
> ```
> ...


Tested it locally. Will work like a charm if you replace "%%*b*" with "%%*c*" 

_________________________________

*N2gadgets*

Glad that we could provide you with solutions and solve that problem!


----------



## foxidrive (Oct 20, 2012)

Grobu said:


> Tested it locally. Will work like a charm if you replace "%%*b*" with "%%*c*"


Nod, ta.



> *N2gadgets*
> 
> Glad that we could provide you with solutions and solve that problem!


Ditto


----------

