Назад | Перейти на главную страницу

Рекурсивно перемещать тысячи файлов во вложенные папки окна

У меня Windows Server с> 300 000 изображений в одной папке.

Я чувствую, что производительность файловой системы падает, и я хотел бы переместить их в подпапки, как предлагали многие другие.

Большинство моих файлов состоят из 10 символов + .jpg - начиная с 1 (например: 1234567890.jpg)

Я хотел бы рекурсивно создавать подпапки на основе имени файла (группы из 3 символов) и перемещать в них файлы. Таким образом, 1234567890.jpg будет перемещен из c: \ images в c: \ Images \ 1 \ 234 \ 567 \ 890.

Как я могу сделать это с помощью командного файла или wscript?

PowerShell - действительно хороший инструмент для этого. Я не собираюсь писать для вас сценарий, но укажу вам правильное направление.

Вы можете перечислить все в каталоге, используя get-childitem и они передают его foreach петля. Затем используйте .substring(0,2) чтобы получить первые три буквы. Сохраните эти три в переменной и создайте папку, используя new-item -Name <foldername> -ItemType folder заменяя переменную, содержащую первые три числа. Было бы неплохо проверить наличие этой папки и делать это только в том случае, если она не существует. Повторите ополаскивание, добавляя логику, которую, вероятно, будет диктовать ваша уникальная ситуация.

Затем вы можете просто использовать move-item для перемещения файлов в папки на основе сопоставления с образцом, учитывающим первые три буквы файла.


Я знаю, ты хотел, чтобы кто-то написал для тебя сценарий, но дай человеку рыбу, научи человека ловить рыбу ...

PowerShell также был бы моим инструментом; на самом деле, я придумал этот однострочный (вроде) для запуска в c: \ images:

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

Запланируйте себе немного PowerShell время, игрушки в ISE и учиться.


Расширенный эквивалент выглядит примерно так:

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

Или более подробно и с примером в комментариях:

# 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"
}

На самом деле я закончил тем, что использовал wscript - поскольку я не играл с PowerShell. Он работал на удивление быстро. Я предположил, что имя файла из 10 символов (до .ext) начинается с 1

Вот копия того, что я запустил:

'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