0

I am trying to write a BAT script to move files into subfolders depending on the filename - without going into too much detail about the explicit purpose of this, the files are named with 2 descriptive prefixes "PREFIX1_PREFIX2_descriptivefilename" - with an underscore delimiter.

I want to move the files into folders according to a few different rules which are dependent on both PREFIX1 and PREFIX2.

This is intended to be used for an in-house system for organising printed documents and images, which are printed on a range of types of paper. For example's sake, lets say we are working with just 2 PREFIX1 types - Class1 and Class2. PREFIX2 can take several forms denoting paper size, let's say for simplicity, "A6paper", "A5paper", "A4paper" and "Larger".

I need the folders to have slightly different filenames to the prefix as any one folder can contain a mix of both PREFIX1 and PREFIX2 document types, as there are a limited number of print types, let's say the folders we are working with are "A5", "A4", "Other", as files with the A6paper and A5paper prefix will both go into "A5".

Here is my example BAT script:

for /f "tokens=1,2* delims=_" %%a in ('dir /B *_*_*.pdf *_*_*.png') do (
    if /I %%a == Class1 (
        if /I %%b == A4paper (
            if not exist "A4" md "A4"
            move "%%a_%%b_%%c" "A4\%%a_%%b_%%c"
        )
        else if /I %%b == A5paper (
            if not exist "A5" md "A5"
            move "%%a_%%b_%%c" "A5\%%a_%%b_%%c"
        )
        else if /I %%b == A6paper (
            if not exist "A5" md "A5"
            move "%%a_%%b_%%c" "A5\%%a_%%b_%%c"
        )
        else if /I %%b == Larger (
            if not exist "Other" md "Other"
            move "%%a_%%b_%%c" "Other\%%a_%%b_%%c"
        )
    )

else if /I %%a == Class2 (
    if /I %%b == A4paper (
        if not exist "A4" md "A4"
        move "%%a_%%b_%%c" "A4\%%a_%%b_%%c"
    )
    else if /I %%b == A5paper (
        if not exist "A5" md "A5"
        move "%%a_%%b_%%c" "A5\%%a_%%b_%%c"
    )
    else if /I %%b == A6paper (
        if not exist "A5" md "A5"
        move "%%a_%%b_%%c" "A5\%%a_%%b_%%c"
    )
    else if /I %%b == Larger (
        if not exist "Other" md "Other"
        move "%%a_%%b_%%c" "Other\%%a_%%b_%%c"
    )
)

else if....

So as you can see this code is already a little unwieldy looking. I am really not sure about the syntax of BAT, whether "else" should be removed entirely as I get some errors using this. Regardless however, the output seems to be nothing like that expected, the code in the nested if clauses seems to be executed randomly regardless of the higher level rules.

I would also ideally like to be able to write something like:

if /I %%b in ("A5paper", "A6paper") (
    if not exist "A5" md "A5"
    move "%%a_%%b_%%c" "A5\%%a_%%b_%%c"
)

...but this does not seem to be allowed.

Any help would be much appreciated.

Xenthide
  • 79
  • 7
  • 2
    _"the files are named with 2 descriptive prefixes "PREFIX1_PREFIX2_descriptivefilename" - with an underscore delimiter"_..., and? Where do you want to move the files to? A clear description of the problem is more important that show a code segment, specially if the code do _not_ works... Please, edit the question; do _not_ post additional details in comments! – Aacini Mar 08 '16 at 16:19
  • Apologies, I have now edited my original post for clarity. – Xenthide Mar 09 '16 at 08:39

2 Answers2

1
for %%a in (A4 A5 Other) do md %%a 2>nul
for /f "tdelims=" %%r in ('dir /B *_*_*.pdf *_*_*.png') do (
 for /f "tokens=1,2* delims=_" %%a in ("%%r") do (
  if /i "%%a"== "Class1" (
   if /i "%%b"=="A4paper" (move "%%r" "a4\" >nul)
   if /i "%%b"=="A5paper" (move "%%r" "a5\" >nul)
   if /i "%%b"=="A6paper" (move "%%r" "a5\" >nul)
   if /i "%%b"=="Larger"  (move "%%r" "Other\" >nul)
  )
  if /i "%%a"== "Class2" (
   if /i "%%b"=="A4paper" (move "%%r" "a4\" >nul)
   if /i "%%b"=="A5paper" (move "%%r" "a5\" >nul)
   if /i "%%b"=="A6paper" (move "%%r" "a5\" >nul)
   if /i "%%b"=="Larger"  (move "%%r" "Other\" >nul)
  )
  )
 )
)

Your problems appear to be substantially ones of logic, but in batch, any else must be placed such that the close-parenthesis before the else keyword and the open-parenthesis after are all on the same physical line.

From your example, you would observe that %%b can only be A4paper, A5paper, A6paper or Larger. The point is that it can't match more than one of these values. Same goes for %%a.

The syntax if "value"=="anothervalue" ... is probably better since it will ensure that the values are processed regardless of any separators (line spaces) which would upset cmd's parsing.

If you create all of the destination directories first, you don't need to create them within your routine, which simplifies matters.

The 2>nul suppresses error messages (like already exists) The >nul suppresses normal messages (like 1 files(s) moved).

The application of the filename to %%r is to simplify - the inner for can process %%r in the manner shown, and %%r conveniently contains the entire name so it doesn't need to be reconstructed.

Again, using the quotes in the move statements means that spaces in filenames are correctly processed.

Magoo
  • 77,302
  • 8
  • 62
  • 84
1

The simplest and most efficient way to solve this problem is via an array: you define in advance a series of array elements that specify the destination folder for each pair of PREFIX1 and PREFIX2. After that, you just process the files using the array data:

@echo off
setlocal EnableDelayedExpansion

rem Define the array for destination folders:

set "folder[Class1,A4paper]=A4"
set "folder[Class1,A5paper]=A5"
set "folder[Class1,A6paper]=A5"
set "folder[Class1,Larger]=Other"

set "folder[Class2,A4paper]=A4"
set "folder[Class2,A5paper]=A5"
set "folder[Class2,A6paper]=A5"
set "folder[Class2,Larger]=Other"

rem Move the files:
for /F "tokens=1,2* delims=_" %%a in ('dir /B *_*_*.pdf *_*_*.png') do (
   if not exist "!folder[%%a,%%b]!" md "!folder[%%a,%%b]!"
   move "%%a_%%b_%%c" "!folder[%%a,%%b]!\"
)

You don't need to repeat the file name in move command.

For a further description of array management in Batch files, see: Arrays, linked lists and other data structures in cmd.exe (batch) script

Community
  • 1
  • 1
Aacini
  • 65,180
  • 12
  • 72
  • 108