Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I have a Windows Server with >300,000 images in a single folder.

I am feeling a performance hit on the filesystem and I would like to move them into subfolders as has been suggested by many others.

Most of my files are 10 characters + .jpg - beginning with a 1 (eg: 1234567890.jpg)

I would like to recursively create subfolders based on file name (groups of 3 characters) - and move the files into them. So 1234567890.jpg would be moved from c:\images into c:\Images\1\234\567\890.

How can I do this with a batch file or wscript?

share|improve this question
add comment

3 Answers

PowerShell is really a good tool for this. I'm not going to write a script for you, but I will point you in the right direction.

You can list everything in the directory using get-childitem and them pass it to a foreach loop. Then, use .substring(0,2) to get the first three letters. Save those three to a variable and create the folder using new-item -Name <foldername> -ItemType folder replacing with the variable holding the first three numbers. It would be a good idea to test for the existence of this folder and only do it if it doesn't exist. Lather rinse repeat adding some logic that your unique situation will likely dictate.

Then, you can just use move-item to move the files into the folders based on pattern matching that looks at the first three letters of the file.


I know you wanted someone to write a script for you, but give a man a fish, teach a man to fish...

share|improve this answer
    
;-) - I actually was wondering if something exists, instead of rolling my own - I know this is fairly common, but couldn't find an existing script. I'll give PowerShell a shake –  user1389579 Jan 23 '13 at 19:18
    
@user1389579 There are batch-rename utilities that can do this. I don't have specific examples. It's been a while since I had a need for something like that. –  Tonny Jan 23 '13 at 19:26
add comment

PowerShell would also be my tool; in fact, I have come up with this one-liner (sort of) to run in c:\images\:

dir *.jpg | %{ $dst = $_.basename -replace '(...)(...)(...)$','\$1\$2\$3'; md $dst >$null 2>&1; move-item $_ -Destination $dst }

Schedule yourself some PowerShell time, toy around in the ISE and learn.


The expanded equivalent is something like this:

dir *.jpg
    | foreach-object
    { 
        $dst = $_.basename -replace '(...)(...)(...)$','\$1\$2\$3'
        md $dst >$null 2>&1
        move-item $_ -Destination $dst
    }

Or, a bit more verbose and with an example in comments:

# if run from "c:\images\", we can get the image list
$images = dir *.jpg

# process images one by one
foreach ($image in $images)
{
    # suppose $image now holds the file object for "c:\images\1234567890.jpg"

    # get its file name without the extension, keeping just "1234567890"
    $filenamewithoutextension = $image.basename

    # group by 3 from the end, resulting in "1\234\567\890"
    $destinationfolderpath = 
        $filenamewithoutextension -replace '(...)(...)(...)$','\$1\$2\$3'

    # silently make the directory structure for "1\234\567\890"
    md $destinationfolderpath >$null

    # move the image from "c:\images\1234567890.jpg" to the new folder "c:\images\1\234\567\890\"
    move-item $image -Destination $destinationfolderpath

    # the image is now available at "c:\images\1\234\567\890\1234567890.jpg"
}
share|improve this answer
    
Thanks! I am going to try to understand your sample - I've never played with powershell. –  user1389579 Jan 24 '13 at 17:54
    
OK, I updated for easier understanding. HTH! –  mousio Jan 24 '13 at 20:13
    
Thanks. I didn't get a chance to try it yet. Hope to update here when I do. –  user1389579 Jan 25 '13 at 16:13
add comment

I actually ended up using wscript - since I haven't played around with PowerShell. It ran surprisingly fast. I assumed 10 character filename (before .ext) starting with a 1

Here's a copy of what I ran:

'On Error Resume Next
Set fso = CreateObject("Scripting.FileSystemObject")
length=10
maindir="C:\inetpub\wwwroot\InventoryImages\"
dodir "C:\inetpub\wwwroot\InventoryImages"


set files=nothing
set folder=nothing
set fso=nothing
wscript.quit


sub dodir(sFolder)
Set folder = fso.GetFolder(sFolder)
Set files = folder.Files
For each file In files
if len(file.name)=length+4 then dofile sfolder,file.name
Next
end sub


sub dofile(dir,filename)
wscript.echo dir & " - " & filename
t_filename=left(filename,10)
t_filename=mid(t_filename,2)
'ASSUMING 1 FIRST DIR
'NOT CHECKING FOR EXISTENCE
t_dir=maindir & "1\"

checkcreate t_dir & left(t_filename,3)
t_dir=t_dir & left(t_filename,3) & "\"
t_filename=mid(t_filename,4)

checkcreate t_dir & left(t_filename,3)
t_dir=t_dir & left(t_filename,3) & "\"
t_filename=mid(t_filename,4)

wscript.echo dir & "\" & filename & "->" & t_dir & filename
fso.movefile dir &"\" & filename,t_dir & filename
end sub


sub checkcreate(dir)
if not fso.FolderExists(dir) then
wscript.echo dir & " does not exist"
fso.CreateFolder(dir) 
end if
end sub
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.