5

How do I sort files into folders, according to file names, using CMD / PowerShell commands?

Let's say I have a folder containing a large amount of files (more than 20,000 files), where all the files have the same naming convention, e.g: (notice the pattern)

t_1001_1801.png
t_1001_1802.png
t_1001_1803.png
...
t_1001_2112.png (last file starts with 't_1001_')
t_1002_1801.png
t_1002_1802.png
t_1002_1803.png
....
t_1002_2112.png
t_1003_1801.png
t_1003_1802.png
t_1003_1803.png
...
t_1214_2112.png (last file in folder)

I run this CMD command to create a list of folders:
for /l %i in (1001,1,1214) do md x%i
which creates a list of folders, e.g:

x1001
x1002
x1003
...
x1214

Now I would like to sort (move) the files into the folders according to the files name, e.g:

- move the files t_1001_1801.png to t_1001_2112.png to the folder x1001.
- move the files t_1002_1801.png to t_1002_2112.png to the folder x1002.
...

Can I use shell commands for this purpose?

  • Check out PFrank File Renamer too, very powerful regex batch tool in a UI, with previewing your renaming/moving: www3.telus.net/pfrank – therobyouknow Jun 3 '18 at 22:59
  • 1
    Not tried this, but how about for /l %i in (1001,1,1024) do md x%i&mv t_%i_* x%i? – Neil Jun 3 '18 at 23:45
8

You simply need to split the FileName, get the number (like 1001), compare the number to the folders, get the correct folder and move the files in there:

# Folder where Files and Folders are located
$TopFolder = "C:\Install"

# Getting Folders and Files
$Folders = gci $TopFolder -OutVariable Files | ? { $_.PSisContainer }

# Loop over all Files with *.png extension
$Files | ? { $_.Extension -eq '.png' } | % {

    # Split FileName to get the number (like 1001)
    $num = ($_.Name -split "_")[1]

    # Get FolderName by reading out foldername (without 'x') and compare it to number
    $MoveTo = $Folders | ? { $_.Name.substring(1,($_.Name.length -1)) -eq $num }

    # If a folder was found, move file there. else print error
    if ($MoveTo)
    {
        Move-Item $_.FullName $MoveTo -Force
        Write-Host "Copied File $($_.Name) to $MoveTo"
    }
    else 
    { 
        Write-Host "Did not find folder x$($num) in $TopFolder" 
    }
}
  • how to run this script? I've created a .bat file and copied the script to it, but the script didn't executed due to errors. – Gil Epshtain Jun 3 '18 at 11:57
  • @GilEpshtain that's a PowerShell Script. you need to create a .ps1file instead of .bat. Then right click - run with powershell – SimonS Jun 3 '18 at 12:11
  • Thanks, it working very well. I only need to change the script a bit, since the actual file name is t_25_1001_1801.png (not as in the original question) so I did this change $num = ($_.Name -split "_")[2]. – Gil Epshtain Jun 3 '18 at 12:27
  • great! yes [2] is correct in that case. – SimonS Jun 3 '18 at 12:39
6

The following batch

  • Changes to the folder to start in
  • iterates with a for command through all *.png file
  • uses a for /f to split the name at the underscores into tokens and uses the 2nd 3rd one to
  • check if a subfolder x with the number exists, if not it is created
  • finally moves the file to the subfolder.

:: Q:\Test\2018\06\03\SU_1328200.cmd
@Echo off 
PushD "C:\Users\UserName\Pictures\"

For %%A in (t_*_*_*.png) do For /F "tokens=3delims=_" %%B in ("%%A") Do (
  If Not exist "x%%B" MD "x%%B"
  Move "%%A" "x%%B"
)
PopD

Sample tree /F after running the batch
(outdated from first requirement with 2nd token)

> tree /F
├───x1001
│       t_1001_1801.png
│       t_1001_1802.png
│       t_1001_1803.png
│       t_1001_2112.png
│
├───x1002
│       t_1002_1801.png
│       t_1002_1802.png
│       t_1002_1803.png
│       t_1002_2112.png
│
├───x1003
│       t_1003_1801.png
│       t_1003_1802.png
│       t_1003_1803.png
│
└───x1214
        t_1214_2112.png

A PowerShell script:

## Q:\Test\2018\06\03\SU_1328200.ps1
PushD  "C:\Users\UserName\Pictures\"
Get-ChildItem t_*_*_*.png |
  Where BaseName -match 't_\d{2}_(\d{4})_\d{4}'|
    Group {'x'+$Matches[1]}|
      ForEach{MD $_.Name;$_.Group|Move -Dest $_.Name}
  • I've try your CMD script and the result wasn't as expected. A list of folders where created (x1001, x1002, ...) and additional folder was created - with the name of the root folder. Than all the files where copied to the folder with the "root" name. The rest of the folders stayed empty. The Shell script didn't run at all due to errors. – Gil Epshtain Jun 3 '18 at 12:07
  • Hmm I tested the batch on my ramdisk without flaw, did you copy paste the batch and changed just the folder following pushd? – LotPings Jun 3 '18 at 12:14
  • 1
    Thank you it was my mistake. I needed to make a small change. Since the actual file name is t_25_1001_1801.png (not as in the original question) I need to make this change For /F "tokens=3delims=_"... – Gil Epshtain Jun 3 '18 at 12:43
  • 1
    Adapted my batch/script. BTW my PowerShell script is more stringent/errorproof/faster/shorter than accepted answer and creates the neccessary folders itself. – LotPings Jun 3 '18 at 12:53
0

Credit to @Neil, for his answer (in the comments), I just want to post it as an answer for others.

for /l %i in (1001,1,1024) do md x%i&move t_%i_* x%i

Explanation:
- Loop on %i from 1001 to 1024 (1 is the iteration step)
- For each iteration do:
1. make directory named x%i (x1001, x1002, ...).
2. move the file matching the regular-expression t_%i_* (t_1001_1801) to the directory x%i (that was just created).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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