Artec
Artec

Reputation: 183

SUBSTRING a filename in batch

I need help to make a batch code (if it's possible) to get substring from filename. My filename can be like (filename lenght is changing):

7_D_D1_012345678-2015-07-07.pdf
8_A_087654321-2015-07-07.pdf
10_D_D1_011122558-2015-07-07.pdf
100_C_CCC1_C2_C3_C4_055555555-2015-07-07.pdf

file number - from left to first _

id1 - from 1 to n string with _ separator; for example C_C1_C2_C3_C4

id2 - always 9 digits; for example 011122558

date - for example 2015-07-07

extension .jpg

How to loop substring (file number, id1, d2, date) for all filenames in folder and put it to my code

convert - "file number" -annotate "id1" -annotate2 "id2" -annotate "date"

for example:

convert - "01" -annotate "C_C1" -annotate2 "012345678" -annotate "2015-07-07"

Thanks for help.

Upvotes: 3

Views: 9519

Answers (3)

MC ND
MC ND

Reputation: 70953

@echo off
    setlocal enableextensions disabledelayedexpansion

    rem For each file
    for /r "x:\starting\folder" %%z in (*.pdf) do (
        rem Separate number part
        for /f "tokens=1,* delims=_" %%a in ("%%~nz") do (
            set "_number=%%~a"
            set "_file=%%~fz"

            rem Separate date and ids 
            for /f "tokens=1,* delims=-" %%c in ("%%~b") do (
                set "_date=%%~d"
                set "_ids=%%~c\."
            )
        )   

        rem Separate id1 from id2 handling the string as a path
        rem This way id2 is the last element and the path to it 
        rem is id1
        setlocal enabledelayedexpansion
        for /f "delims=" %%e in ("::!_ids:_=\!") do (
            endlocal
            set "_id2=%%~nxe"
            set "_id1=%%~pe"
        )

        rem Correct id1 contents (it is a path) changing backslashes 
        rem to underscores. As there are initial and ending backslashes,
        rem later we will remove the initial and ending underscores
        setlocal enabledelayedexpansion
        for /f "delims=" %%e in ("!_id1:\=_!") do (
            endlocal
            set "_id1=%%~e"
        )

        rem Execute final command 
        setlocal enabledelayedexpansion
        echo(
        echo file[!_file!] 
        echo convert - "!_number!" -annotate "!_id1:~1,-1!" -annotate2 "!_id2!" -annotate "!_date!"
        endlocal

    )

Upvotes: 1

Ross Presser
Ross Presser

Reputation: 6255

Since you said Windows 7, I know you have Powershell available. Here is a Powershell script:

$re = '^(\d+)_((?:(?:[a-zA-Z0-9]+)_?)+)_(\d{9})-(\d{4}-\d\d-\d\d)\.(\w+)$'
dir | ForEach-Object {$_ -replace $re, 'convert "$1" -annotate "$2" -annotate2 "$3" -annotate3 "-$4"'}

Given the filenames you gave in your question

7_D_D1_012345678-2015-07-07.pdf
8_A_087654321-2015-07-07.pdf
10_D_D1_011122558-2015-07-07.pdf
100_C_CCC1_C2_C3_C4_055555555-2015-07-07.pdf

It will produce this text output:

convert "100" -annotate "C_CCC1_C2_C3_C4" -annotate2 "055555555" -annotate4 "2015-07-07"
convert "10" -annotate "D_D1" -annotate2 "011122558" -annotate4 "2015-07-07"
convert "7" -annotate "D_D1" -annotate2 "012345678" -annotate4 "2015-07-07"
convert "8" -annotate "A" -annotate2 "087654321" -annotate4 "2015-07-07"

(The filenames were sorted first, so the one starting with 100 comes first and the one starting with 8 comes last).

By redirecting this text output into a .cmd file, you can execute the convert commands as desired.

Here is the breakdown of that regular expression:

Beginning of line or string
[1]: A numbered capture group. [\d+]
    Any digit, one or more repetitions
_
[2]: A numbered capture group. [(?:(?:[a-zA-Z0-9]+)_?)+]
    Match expression but don't capture it. [(?:[a-zA-Z0-9]+)_?], one or more repetitions
        (?:[a-zA-Z0-9]+)_?
            Match expression but don't capture it. [[a-zA-Z0-9]+]
                Any character in this class: [a-zA-Z0-9], one or more repetitions
            _, zero or one repetitions
_
[3]: A numbered capture group. [\d{9}]
    Any digit, exactly 9 repetitions
-
[4]: A numbered capture group. [\d{4}-\d\d-\d\d]
    \d{4}-\d\d-\d\d
        Any digit, exactly 4 repetitions

Upvotes: 2

Stephan
Stephan

Reputation: 56188

pure batch. Simple string manipulation mixed with tokenization. No need for additional utilities.

(g.txt holds your example file names; could be replaced by 'dir /b /a-d')

@echo off
for /f %%i in (g.txt) do call :process %%i
goto :eof

:process
set x=%1
set ext=%x:*.=%
for /f "delims=_" %%i in ("%x%") do set fileno=%%i
for /f "tokens=1,*delims=-" %%i in ("%x%") do (
  set x1=%%i
  set x2=%%j
)
for /f "tokens=1,* delims=." %%i in ("%x2%") do (
  set dat=%%i
  set ext=%%j
)
set id2=%x1:~-9%
for /f "tokens=1,* delims=_" %%i in ("%x1:~0,-10%") do set id1=%%j
echo filename   %x%
echo ------------------------
echo    Nr. %fileno%
echo    ID1 %id1%
echo    ID2 %id2%
echo    Date    %dat%
echo    Ext.    %ext%
echo ------------------------
echo convert - "%fileno%" -annotate "%id1%" -annotate2 "%id2% -annotate "%dat%"
echo(
echo(
goto :eof

Upvotes: 3

Related Questions