Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I've been trying to figure out how to make a dos command that can "see" part of a file name, then create a folder and sort every file which has that part of a filename in it.

Every filename has the following characters (excluding the extension):

3 letters, 5 digits, 1 letter, 1 digit

For example: BBB12345B0

Each letter and number in the filename can vary, but the filename will always have the same build.

What the script is supposed to do is recognize only the 5 digits, then create a folder from those 5 digits and then move those files to that folder.

The following i found on the internet:

@echo off
for /f "delims=" %%a in ('dir /b /a-d') do (

if not "%%~fa"=="%~f0" (

md "%%~na" 2>nul

if exist "%%a" move "%%~na.*" "%%~na"

)

)

This works great, except that the whole filename is used to create a folder and sort the files. I want the script to do the same thing but only using the 5 digits.

I've tried to work with "tokens" in this script. Also used some onther methods but none of them work properly. I'm also not so familiar with this kind of batch scripting. Can anyone help me with this?

share|improve this question

4 Answers 4

Ahead of the answers with CMD scripts for a change, here's a different way, using JP Software's TCC/LE, an alternative command interpreter:

@echo off
for %file in ([a-z][a-z][a-z][0-9][0-9][0-9][0-9][0-9][a-z][0-9].*) do ( 
    mkdir 2>NUL "%@instr[3,5,%file%]"
    ren "%file%" "%@instr[3,5,%file%]\%file%"
)

Note that the rather long wildcard follows your specification, and will not include filenames that have different letter-digit patterns. A less restrictive wildcard would be [?][?][?][?][?][?][?][?][?][?].*, which matches every filename that is exactly 10 characters long, sans extension. Also note that there's no need for an explicit /a:-d with for, since excluding directories is already the default.

Use the /n option to the ren command to display what would happen without moving the files.

It's madness to parse the output of dir /b with for, by the way. Even in Microsoft's CMD, for does search wildcards itself.

Further reading

  • FOR. TCC/LE command reference. JP Software.
  • @INSTR. TCC/LE command reference. JP Software.
share|improve this answer
    
Hello |JdeBP. I've tried both sollutions given by JdeBP, but I get a "file not expected" error. –  Erik Feb 17 at 15:20
    
That error results from running the script in the wrong command interpreter. Use the one mentioned in the first sentence of the answer. –  JdeBP Feb 17 at 17:51

Hello JdeBP and Martin,

I've tried both sollutions given by JdeBP, but I get a "file not expected" error. The powershell option by Martin looks like a good option. I will look further if this kind of batch scripting if i have to use it more

share|improve this answer

In PowerShell:

$files = gci . | where {!$_.psIsContainer}
foreach ($file in $files) {
    $dir = $file.Name.Substring(3, 5)
    if (!(test-path -path $dir)) {
        mkdir $dir
    }
    mv $file $dir
}

Assuming your files are in the current directory.

share|improve this answer

If it's a possibility, you should switch to PowerShell instead, it can be installed on WinXP and is included by default on Windows Vista and up, so no need to install anything. It has a lot of tools which makes a lot of the jobs that's a hassle in batch, really simple. And it also allows you to use com-objects and the .net library in a pinch.

It also allows you to use Regular Expressions which makes what you want to do that much easier, and on top of that, you can use regular ol' batch tools in it, like "mkdir" if you want, allthough it's rearly needed.

There's a lot of good tutorials if you search the web for "powershell tutorial", etc.

(If I have time later I'll make a simple script that'll do the task you need.)

Edit: Also it's alot more readable than batch^^

Edit2: Short script that does what you need:

$dir="X:\Your\Path";

get-childitem $dir | %{

    $file=$_;
    if(-not $file.PSIsContainer)
    {
        if($file.PSChildName -match "^.*(\w{3})(\d{5})(\w{1})(\d{1}).*$")
        {
            $folder = "$($file.PSParentPath)\$($matches[2])";

            if(test-path $folder)
            {
                Move-Item "$($file.PSPath)" "$folder\$($file.PSChildName)";
            }
            else
            {
                mkdir $folder;
                Move-Item "$($file.PSPath)" "$folder\$($file.PSChildName)";
            }
        }
    }
}
share|improve this answer
    
Hello Martin. The powershell option looks like a good option. I will look further if this kind of batch scripting if i have to use it more –  Erik Feb 17 at 15:21
    
Hello Martin. I tried using the script in Powershell. I get the following error: File G:\test.ps1 cannot be loaded because the execution of scripts is disabled on this system. Please see "get-help about_signing " for more details. I'm in my work environment. I probably do not have the authorisation to ruin these kinds of scripts. –  Erik Feb 18 at 7:32
    
Try to open up powershell and write "Set-ExecutionPolicy RemoteSigned". –  Martin Feb 18 at 10:09
    
Hello Martin. Get the same error. Just before PS start I also get three errors. On e of them is as follows: PID=4820, runtime2.cpp@841. I googled this, but it didn't get me any further (to technical). However, i did found the sollution to my problem on a other forum. This person came up with the following batch. setlocal enabledelayedexpansion for /f "delims=" %%a in ('dir /b /a-d') do ( if /i not "%%a"=="%~nx0" ( echo bezig met verplaatsen van "%%a" set "name=%%a" md "!name:~3,5!" 2>nul move "%%a" "!name:~3,5!" >nul ) ) The results are very good. –  Erik Feb 19 at 12:57
    
Just tried powershell on colleague terminal. Same problem unfortunately. –  Erik Feb 19 at 13:27

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.