batch file string manipulation in for loop

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Tom48
Posts: 6
Joined: 23 Nov 2016 13:39

batch file string manipulation in for loop

#1 Post by Tom48 » 23 Nov 2016 13:44

hi,

im pretty new ro batch programming and i just can not get it done.
I already spend hours and this so i really hope some of you guys are able to help me out! :)

I have many .txt files in a local folder named like e.g: 0200_some_other_stuff_0x201548_5555.txt

Now i would like to zip this files.
Heres the big problem i can not solve:
I want the name of the zipped folder to depend on the zipped file.
If the file name is: 0200_some_other_stuff_0x201548_5555.txt
i would like the zipped folder to be named: 0200_NEW_NAME_0x201548_5555.zip
So basically i would like to keep the numbers from the old name string and only replace the middle part with smth. new.
Is this possible?

How do i do the string manipulation in the loop?
Do i need to set the file name into a variable and then manipulate it to extract the string part i want?
How would i do that?

This is what i got:

Code: Select all

    SETLOCAL ENABLEDELAYEDEXPANSION
    @echo off

    FOR /r %%A IN (*.txt) DO (
 
    M:\7-Zip\7z.exe a  "%%~nA.zip" "%%~nA.txt"
    pause
    )


Also this does zip only one single file and not all .txt files that are in the folder.
Do you know what im doing wrong?

I would really appreciate some help guys, so many thanks in advance! :)

EDIT: removed the recursive parameter in my example code.
Last edited by Tom48 on 23 Nov 2016 14:19, edited 1 time in total.

Squashman
Expert
Posts: 4465
Joined: 23 Dec 2011 13:59

Re: batch file string manipulation in for loop

#2 Post by Squashman » 23 Nov 2016 13:55

Could you please provide better real world examples of your file names please.

Also a bit confused by your code because you are recursing folders with the FOR command and then you are recursing with your 7zip command.

Squashman
Expert
Posts: 4465
Joined: 23 Dec 2011 13:59

Re: batch file string manipulation in for loop

#3 Post by Squashman » 23 Nov 2016 14:00


Tom48
Posts: 6
Joined: 23 Nov 2016 13:39

Re: batch file string manipulation in for loop

#4 Post by Tom48 » 23 Nov 2016 14:12

hi,

thank you for your fast reply!

in my folder there are like 100 text files.
They have names like this:

0200_db_off_state_0x201548_5555.txt
0200_db_off_state_0x201548_5556.txt
0200_db_off_state_0x201448_5558.txt
0201_db_on_state_0x201448_5525.txt
0201_db_on_state_0x201448_5535.txt
0201_db_on_state_0x201448_5555.txt
0204_db_sleep_state_0x201648_5235.txt
0204_db_sleep_state_0x201648_5236.txt
0204_db_sleep_state_0x201648_5233.txt

they all shall be zipped into a signel zipped folder each.
The folders names are dependant on the file that has been zipped.
In this case the zipped folders of the files that are listed above should be named like this:

0200_DB_STATE_0x201548_5555.zip
0200_DB_STATE_0x201548_5556.zip
0200_DB_STATE_0x201448_5558.zip
0201_DB_STATE_0x201448_5525.zip
0201_DB_STATE_0x201448_5535.zip
0201_DB_STATE_0x201448_5555.zip
0204_DB_STATE_0x201648_5235.zip
0204_DB_STATE_0x201648_5236.zip
0204_DB_STATE_0x201648_5233.zip

How would you try to solve this issue?
Im really overchallenged with this task right now as i never had to do batch programming before so i really hope i can learn from you.

thank you! :)

Squashman
Expert
Posts: 4465
Joined: 23 Dec 2011 13:59

Re: batch file string manipulation in for loop

#5 Post by Squashman » 23 Nov 2016 14:39

You have not specified where you want the zip file saved to. Do you want it in the same directory of the input file or some other directory?

Tom48
Posts: 6
Joined: 23 Nov 2016 13:39

Re: batch file string manipulation in for loop

#6 Post by Tom48 » 23 Nov 2016 14:46

just the same directory, is just fine :)

Squashman
Expert
Posts: 4465
Joined: 23 Dec 2011 13:59

Re: batch file string manipulation in for loop

#7 Post by Squashman » 23 Nov 2016 14:54

This should get you close. I am just echoing the commands to the screen. When the output on the screen looks correct, remove the ECHO before the 7zip command.

Code: Select all

@echo off
FOR /R %%G IN (*.txt) DO (
   FOR /F "tokens=1,2,3* delims=_" %%H IN ("%%~nG") DO (
      ECHO M:\7-Zip\7z.exe a  "%%~dpG%%H_%%I_%%K.zip" "%%~G"
   )
)
pause


Using your file examples. I created this folder structure.

Code: Select all

C:\BatchFiles\zip>dir /a-d /b /s *.txt
C:\BatchFiles\zip\0204_db_sleep_state_0x201648_5233.txt
C:\BatchFiles\zip\0204_db_sleep_state_0x201648_5235.txt
C:\BatchFiles\zip\0204_db_sleep_state_0x201648_5236.txt
C:\BatchFiles\zip\Folder1\0200_db_off_state_0x201448_5558.txt
C:\BatchFiles\zip\Folder1\0200_db_off_state_0x201548_5555.txt
C:\BatchFiles\zip\Folder1\0200_db_off_state_0x201548_5556.txt
C:\BatchFiles\zip\Folder2\0201_db_on_state_0x201448_5525.txt
C:\BatchFiles\zip\Folder2\0201_db_on_state_0x201448_5535.txt
C:\BatchFiles\zip\Folder2\0201_db_on_state_0x201448_5555.txt


The batch file was then executed from the ZIP Folder. Which produced this output.

Code: Select all

M:\7-Zip\7z.exe a  "C:\BatchFiles\zip\0204_db_state_0x201648_5233.zip" "C:\BatchFiles\zip\0204_db_sleep_state_0x201648_5233.txt"
M:\7-Zip\7z.exe a  "C:\BatchFiles\zip\0204_db_state_0x201648_5235.zip" "C:\BatchFiles\zip\0204_db_sleep_state_0x201648_5235.txt"
M:\7-Zip\7z.exe a  "C:\BatchFiles\zip\0204_db_state_0x201648_5236.zip" "C:\BatchFiles\zip\0204_db_sleep_state_0x201648_5236.txt"
M:\7-Zip\7z.exe a  "C:\BatchFiles\zip\Folder1\0200_db_state_0x201448_5558.zip" "C:\BatchFiles\zip\Folder1\0200_db_off_state_0x201448_5558.txt"
M:\7-Zip\7z.exe a  "C:\BatchFiles\zip\Folder1\0200_db_state_0x201548_5555.zip" "C:\BatchFiles\zip\Folder1\0200_db_off_state_0x201548_5555.txt"
M:\7-Zip\7z.exe a  "C:\BatchFiles\zip\Folder1\0200_db_state_0x201548_5556.zip" "C:\BatchFiles\zip\Folder1\0200_db_off_state_0x201548_5556.txt"
M:\7-Zip\7z.exe a  "C:\BatchFiles\zip\Folder2\0201_db_state_0x201448_5525.zip" "C:\BatchFiles\zip\Folder2\0201_db_on_state_0x201448_5525.txt"
M:\7-Zip\7z.exe a  "C:\BatchFiles\zip\Folder2\0201_db_state_0x201448_5535.zip" "C:\BatchFiles\zip\Folder2\0201_db_on_state_0x201448_5535.txt"
M:\7-Zip\7z.exe a  "C:\BatchFiles\zip\Folder2\0201_db_state_0x201448_5555.zip" "C:\BatchFiles\zip\Folder2\0201_db_on_state_0x201448_5555.txt"

Tom48
Posts: 6
Joined: 23 Nov 2016 13:39

Re: batch file string manipulation in for loop

#8 Post by Tom48 » 23 Nov 2016 15:24

ok, that works extremely well!
Thanks a lot!

How could i delete the Text File is just zipped? Could i just use the del command in the inner loop? How exactly would u do that?

Could you maybe tell me why you are using "tokens=1,2,3*" and "delims=_" ? (what exactly is it doing?)
Also i do not understand the last part of this: "%%~dpG%%H_%%I_%%K.zip" (the bold red part)
I would be very happy if you could leave a short comment on these things.
I have a lot of work to do in order to get fit here (i will have to do it) but i think some starter help like this might speed up the process a lot! :)

Two more problems i didnt know how to solve:

1.
Would it also be possible to write a script like this:
removing the middle text part (db_off_state, db_on_state etc.) and change it to a specified string i have defined at the top?


2.
Imagine some of the text files also could have slightly different names like (some have 4 digits and some have 5 digits at the beginning):

0200_db_off_state_0x201548_5555.txt (4 digits at the beginning)
0200_db_off_state_0x201548_5556.txt (4 digits at the beginning)
02001_db_off_state_0x201448_5558.txt (5 digits at the beginning)
02002_db_off_state_0x201448_5558.txt (5 digits at the beginning)
Your script still can rename/zip them correctly, how does it work?

Thanks a lot for all the help, i really appreciate it a lot!
Sorry for bothering you that much!

Squashman
Expert
Posts: 4465
Joined: 23 Dec 2011 13:59

Re: batch file string manipulation in for loop

#9 Post by Squashman » 23 Nov 2016 19:57

Tom48 wrote:How could i delete the Text File is just zipped? Could i just use the del command in the inner loop? How exactly would u do that?

Doesn't matter. As long as it is done after the 7zip command. Just use the delete command with the outer FOR variable.

Tom48 wrote:Could you maybe tell me why you are using "tokens=1,2,3*" and "delims=_" ? (what exactly is it doing?)

It is specifying how to split up the file name. It is using the underscore as the delimiter to split the file name into multiple "TOKENS" In this case 4 tokens. The first token gets assigned to the FOR variable %%H, the second token gets assigned to %%I, etc.... It goes in alphabetical sequence. Well in reality it is in ascii sequence but I don't want to confuse you with that.

So take your first file name:

Code: Select all

0204_db_sleep_state_0x201648_5233.txt

Code: Select all

%%H = 0204
%%I = db
%%J = sleep

Now here is the somewhat confusing part. I said the file name is split into 4 tokens but I did not specify 4 directly. It is specified indirectly by putting an asterisk after the last token number. The asterisk means to assign the remaining portion of the variable to the last token. In this case token 4 which is:

Code: Select all

%%K = state_0x201648_5233

Notice that it does not split apart the remaining part of the file name that has underscores.

Everything I just said above should answer this question.
Tom48 wrote:Also i do not understand the last part of this: "%%~dpG%%H_%%I_%%K.zip" (the bold red part)




Now that I have explained how the FOR command works with delimiters you should be able to answer this question yourself.
Tom48 wrote:1.
Would it also be possible to write a script like this:
removing the middle text part (db_off_state, db_on_state etc.) and change it to a specified string i have defined at the top?


And I am pretty sure all my explanations above answers this question as well. It all has to do with the delimiter. The rest of the characters in the file name are irrelevant.
Tom48 wrote:2.
Imagine some of the text files also could have slightly different names like (some have 4 digits and some have 5 digits at the beginning):

0200_db_off_state_0x201548_5555.txt (4 digits at the beginning)
0200_db_off_state_0x201548_5556.txt (4 digits at the beginning)
02001_db_off_state_0x201448_5558.txt (5 digits at the beginning)
02002_db_off_state_0x201448_5558.txt (5 digits at the beginning)
Your script still can rename/zip them correctly, how does it work?

Tom48
Posts: 6
Joined: 23 Nov 2016 13:39

Re: batch file string manipulation in for loop

#10 Post by Tom48 » 24 Nov 2016 14:01

Thank you so much for the help!
This helped me so much to understand all the expansions and loops.

One more question.
In case i have some loops that include a path (like in the following).
How could i set/define the path into a variable/string at the top so i have to change the path only at the top once if necesarry and not in every loop.
Would you use a set command at the top or do it differently?

Code: Select all

somehow define the path here:
set "defined_path_string=/some/path/..."

loop 1:
for /r %d in ("/some/path/...") do ...
loop 2:
for /r %d in ("/some/path/...") do ...
loop 3:
for /r %d in ("/some/path/...") do ...


Thank you so much!
Have a great day! :D

Squashman
Expert
Posts: 4465
Joined: 23 Dec 2011 13:59

Re: batch file string manipulation in for loop

#11 Post by Squashman » 24 Nov 2016 16:43

With a FOR /R you specify the path after the /R. Read the help for the command. You would not put it into the IN clause when using /R.

Tom48
Posts: 6
Joined: 23 Nov 2016 13:39

Re: batch file string manipulation in for loop

#12 Post by Tom48 » 25 Nov 2016 15:11

Sorry, i intended to write this:

Code: Select all

somehow define the path here:
set "defined_path_string=C:\some\path\"

loop 1:
FOR /R "C:\some\path\" %%G IN (*.txt) DO ...
loop 2:
FOR /R "C:\some\path\" %%G IN (*.txt) DO ...
loop 3:
FOR /R "C:\some\path\" %%G IN (*.txt) DO ...


I would like to set a variable/string somehow at the top so i dont have to change the path in every loop manually in case i need to adjust the path but only
in the defined variable/string at the top.

Would i use the set command here or is there a better way to do this?
Could i also do this with the set command?

thank you so much for your efforts! :)

as my idea would just be this:

Code: Select all

@echo off
Setlocal EnableDelayedExpansion
set SomePath="C:\test_folder\"

FOR /R "%SomePath%" %%G IN (*.txt) DO (
REM ...
)
pause

I wouldnt need the Setlocal EnableDelayedExpansion defining right here right? (because i do not change the variable at runtime, is that right?)

Post Reply