6

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?

2
  • Check out PFrank File Renamer too, very powerful regex batch tool in a UI, with previewing your renaming/moving: www3.telus.net/pfrank Jun 3, 2018 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, 2018 at 23:45

3 Answers 3

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" 
    }
}
4
  • 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. Jun 3, 2018 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, 2018 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]. Jun 3, 2018 at 12:27
  • great! yes [2] is correct in that case.
    – SimonS
    Jun 3, 2018 at 12:39
7

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}
4
  • 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. Jun 3, 2018 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, 2018 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=_"... Jun 3, 2018 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, 2018 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).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .