RisaAudr
RisaAudr

Reputation: 53

Batch Script - Rename files, removing a variable prefix and suffix

I have several files in a folder with names like

"prefix (S-N 12RE3123) suffix.pdf"

I would like to rename them to just "12RE3123.pdf", removing the prefix and suffix. The issue is that both the prefix and suffix are of varying lengths/ characters, so I cannot just rename by removing the first/last xx characters, but have to use the only commonality where only the characters inside the parenthesis following "S-N" are those to be kept.

There is one special case where a few of the serial numbers are named as WD-12RE3123, and I need to remove the WD- as well. If I had to do it manually, there aren't a lot of them like that so it wouldn't be the end of the world, but having it automated would be nice. I thought of maybe doing an if statement after the removal of prefix/suffix to check if the first 3 characters match WD- then remove those if true, but I am not sure on the implementation.

I am still a novice in batch or vbscript, so I was wondering if this can be done in either of those. Batch has the method "REN" to rename files, but since the final name depends upon what the current name is I am not sure how to set up delimiters or how to approach this.

Any assistance would be greatly appreciated.

Upvotes: 0

Views: 3438

Answers (3)

dbenham
dbenham

Reputation: 130829

Magoo and aschipfl both provided good pure batch solutions.

I find development of custom batch scripts for every complex renaming task to be tedious, which is why I wrote JREN.BAT - a regex find/replace renaming utility. JREN.BAT is pure script (hybrid JScript/batch) that runs natively on any Windows machine from XP onward. Full documentation is available from the command line via jren /?, or use jren /?? for paged help.

With JREN.BAT, the solution is as simple as (untested):

jren "^.*\((?:S-N (?:WD-)?)(.+?)\).*" "$1.jpg" /fm *.jpg

If I got the regex wrong, it can easily be fixed. You should probably add the /T option to run the command in test mode first, and then remove it when everything looks good.

If you put the command in a batch script, then you must use CALL JREN.

Upvotes: 1

aschipfl
aschipfl

Reputation: 34909

Here is a simple solution for your request. It relies on the following facts:

  • the prefix portion does not contain any parenthesis ( or ) on its own (suffix might though);
  • the serial number does not contain any parentheses ( or ) on its own;
  • there are no duplicate serial numbers, also with respect to removal of potentional WD- strings;

This is the code (after having tested the code on the files in your target folder, you need to remove the upper-case ECHO command to actually rename the files):

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Set constants here:
set "LOCATION=.\test"
set "PATTERN=*.pdf"
set STRINGS="S-N " "WD-"

cd /D "%LOCATION%"
for /F "eol=| delims=" %%K in ('dir /B "%PATTERN%"') do (
    for /F "eol=| tokens=2 delims=()" %%L in ("%%~nK") do (
        set "NAME=%%L"
        setlocal EnableDelayedExpansion
        for %%J in (%STRINGS%) do (
            if "!NAME!"=="%%~J!NAME:*%%~J=!" (
                set "NAME=!NAME:*%%~J=!"
            )
        )
        ECHO ren "%%~fK" "!NAME!%%~xK"
        endlocal
    )
)

endlocal
exit /B

How it works:

  • the first section specifies the folder location, the file pattern and the strings to remove (after having extracted the portion within ()); adapt the values to your needs;
  • there are several nested for loops; the outermost one simply iterates all the files matching the given pattern (it basically reads and parses the output of a dir command applied on the given files and loops through the returned items; opposed to a standard for loop, this for /F method ensures that the entire folder is read before the loop starts iterating, which is necessary when modifying the enumerated folder content like we do here by renaming files; see also this thread about that issue);
    • the next for /F loop extracts the file name portion of interest, that is everything between the first pair of parenthesis, and stores it in variable NAME; this loop iterates once only per file;
      • the is another for loop which walks though all items in the STRINGS variable;
        • the if clause checks whether the current item of STRINGS occurs at the very beginning of the NAME value; if so, it is removed, otherwise not; this is just a safety query because perhaps a serial number might also contain a given STRINGS item in the middle or at the end (for instance, 123-WD-45A);
      • at this point, the renaming is performed (after having removed ECHO, of course);
      • the toggling of delayed expansion is intended to avoid trouble with some special characters in the file names;

And here is another script that uses a more complex method for extracting the interesting parts of the file names. It relies on the following facts:

  • there occurs only a single substring (S-NSPACE in the file name
  • the serial number is followed by a );
  • the serial number does not contain any parentheses ( or ) on its own;
  • there are no duplicate serial numbers, also with respect to removal of potentional WD- strings;

The code looks like this:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Set constants here:
set "LOCATION=.\test"
set "PATTERN=*.pdf"
set "FILTER=(S-N [^()][^()]*)"
set "IDENTIFYER=S-N "
set STRINGS="WD-"

cd /D "%LOCATION%"
for /F "eol=| delims=" %%K in ('
    dir /B "%PATTERN%" ^| findstr /I /R /C:"%FILTER%"
') do (
    set "NAME=%%K"
    setlocal EnableDelayedExpansion
    set "NAME=!NAME:*(%IDENTIFYER%=!"
    for /F "eol=| tokens=1 delims=)" %%L in ("!NAME!") do (
        setlocal DisableDelayedExpansion
        set "NAME=%%L"
        setlocal EnableDelayedExpansion
        for %%J in (%STRINGS%) do (
            if "!NAME!"=="%%~J!NAME:*%%~J=!" (
                set "NAME=!NAME:*%%~J=!"
            )
        )
        ECHO ren "%%~fK" "!NAME!%%~xK"
        endlocal
        endlocal
    )
    endlocal
)

endlocal
exit /B

Basically, this script works similar to the above one, with a few deviations:

  • the first section specifies a file name filter and the serial number identifyer (S-N) in addition;
  • the dir command in the outermost for loop is piped into a findstr command to filter out files not containing (S-N and ) and a string (not containing (/)) in between already at the beginning;
    • the part (S-N and everything before is removed, the result is stored in NAME;
    • the next for /F loop extracts everything up to but not including the first ) from the NAME value, which constitutes the file name portion of interest; this loop iterates once only per file;
      • the is another for loop which walks though all items in the STRINGS variable, which does not contain the S-N portion here as this has already been removed before; the rest in this loop is the same as in the above script;
      • at this point, the renaming is performed (after having removed ECHO, of course);

Upvotes: 2

Magoo
Magoo

Reputation: 80023

@ECHO Off
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "delims=" %%a IN (
 'dir /b /a-d "%sourcedir%\*(*)*.*" '
 ) DO (
 FOR /f "tokens=1,2delims=()" %%c IN ("%%a") DO (
  FOR /f "tokens=1-3delims=- " %%m IN ("%%d") DO (
   IF "%%o"=="" (ECHO(REN "%sourcedir%\%%a" "%%n%%~xa"
   ) ELSE (
    ECHO(REN "%sourcedir%\%%a" "%%o%%~xa"
   )
  )
 )
)

GOTO :EOF

You would need to change the setting of sourcedir to suit your circumstances.

The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(REN to REN to actually rename the files.

Apply each filename matching the mask "()." to %%a

Tokenise using ( and ) as delimiters so that the parenthesised portion is in %%d Re-tokenise using - and as delimiters so that the required number is in %%o for S-N patterns and %%n for WD- pattern.

Show the rename line.

Note: this should work provided the prefix portion does not contain parentheses and the parenthesised portion is exactly as described.

Upvotes: 1

Related Questions