2 votes

Déplacer récursivement des milliers de fichiers dans des sous-dossiers Windows

J'ai un serveur Windows avec plus de 300 000 images dans un seul dossier.

Je ressens une baisse de performance sur le système de fichiers et je voudrais les déplacer dans des sous-dossiers comme cela a été suggéré par beaucoup d'autres personnes.

La plupart de mes fichiers ont 10 caractères + .jpg - commençant par un 1 (ex : 1234567890.jpg)

Je voudrais créer récursivement des sous-dossiers basés sur le nom du fichier (groupes de 3 caractères) - et y déplacer les fichiers. Ainsi, 1234567890.jpg serait déplacé de c : \images en c : \Images\1\234\567\890.

Comment puis-je faire cela avec un fichier batch ou un wscript ?

3voto

MDMarra Points 99815

PowerShell est vraiment un bon outil pour cela. Je ne vais pas écrire un script pour vous, mais je vais vous indiquer la bonne direction.

Vous pouvez lister tout ce qui se trouve dans le répertoire en utilisant get-childitem et le passe à un foreach boucle. Ensuite, utilisez .substring(0,2) pour obtenir les trois premières lettres. Enregistrez ces trois lettres dans une variable et créez le dossier en utilisant new-item -Name <foldername> -ItemType folder en remplaçant par la variable contenant les trois premiers chiffres. Ce serait une bonne idée de tester l'existence de ce dossier et de ne le faire que s'il n'existe pas. Lather rinse repeat en ajoutant une certaine logique que votre situation unique va probablement dicter.

Ensuite, vous pouvez simplement utiliser move-item pour déplacer les fichiers dans les dossiers en se basant sur une correspondance de motifs qui examine les trois premières lettres du fichier.


Je sais que vous vouliez que quelqu'un écrive un script pour vous, mais donnez un poisson à un homme, apprenez-lui à pêcher...

1voto

mousio Points 736

PowerShell serait également mon outil ; en fait, j'ai créé cette ligne unique (en quelque sorte) à exécuter en c : \images :

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

Prévoyez un peu de PowerShell temps, jouer dans le ISE y apprendre .


L'équivalent élargi est quelque chose comme ceci :

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

Ou, un peu plus verbeux et avec un exemple dans les commentaires :

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

0voto

Mohammad Ahmad Points 223

En fait, j'ai fini par utiliser wscript - puisque je n'ai pas joué avec PowerShell. Cela a fonctionné étonnamment vite. J'ai supposé un nom de fichier de 10 caractères (avant .ext) commençant par un 1.

Voici une copie de ce que j'ai fait :

'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

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X