Split a filename containing wildcards in path and name without expanding the wildcards

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Alsart
Posts: 4
Joined: 29 Nov 2024 17:58

Split a filename containing wildcards in path and name without expanding the wildcards

#1 Post by Alsart » 01 Dec 2024 21:41

I want to split a filename that contains wildcards in "drive:path" and "name.ext"
For example:
@echo off
echo path=%~dp1
echo name=%~nx1

It works if the filename does not contain wildcards, i.e. with filename=c:\mypath\myname.ext you get
path=c:\mypath\
name=myname.ext
But it does not work if the filename contains wildcards, i.e. filename=c:\mypath\*.c
I would like to obtain:
path=c:\mypath\
name=*.c
But the syntax %~nx1 expands the wildcards. If there is no any file that can be expanded by the wildcards you get the correct result but, if for example a file named c:\mypath\myname.c exists, then you get:
path=c:\mypath\
name=myname.c

How can I split without expanding the wildcards?
Thanks

alderman
Posts: 1
Joined: 04 Dec 2024 02:38

Re: Split a filename containing wildcards in path and name without expanding the wildcards

#2 Post by alderman » 04 Dec 2024 02:41

Did you try escaping the wildcards or handle them as literal strings before processing?

Alsart
Posts: 4
Joined: 29 Nov 2024 17:58

Re: Split a filename containing wildcards in path and name without expanding the wildcards

#3 Post by Alsart » 05 Dec 2024 03:21

Thanks for the suggestion.
If you escape * and ? in the command line with ^^* and ^^? then %~nx1 works. But if you write * and ? directly in the command line (without escaping them), the problem is to escape these characters inside the bat script.
? can be easily escaped with string substitution:
set var=%~1
set "varescaped=%var:?=^^?%"
But * cannot be used with string substitution because * is a reserved char in string substitution.
Some possible solutions can be found but they are not simple and require to go one by one through all the chars in the string to do the substitution. In this case it's not worth using this solution because if you need going through all chars in the string, it seems preferable to implement the split_path_name function directly looking for the chars : and \ in the string as separators between the path and the name.

Aacini
Expert
Posts: 1920
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Split a filename containing wildcards in path and name without expanding the wildcards

#4 Post by Aacini » 06 Dec 2024 14:33

This simple one-liner works no matter the number nor the position of the wildcards:

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set "filename=c:\one\two\*\four\*.c"

set "fpath=%filename:\=" & set "fpath=!fpath!!name!" & set "name=\%" & set "name=!name:~1!"

echo filename=%filename%
echo path=%fpath%
echo name=%name%
Output:

Code: Select all

filename=c:\one\two\*\four\*.c
path=c:\one\two\*\four
name=*.c
Antonio

OJBakker
Expert
Posts: 93
Joined: 12 Aug 2011 13:57

Re: Split a filename containing wildcards in path and name without expanding the wildcards

#5 Post by OJBakker » 07 Dec 2024 03:31

Antonio
Your code gives incorrect output for the path:

Code: Select all

filename=c:\one\two\*\four\*.c
path=c:.c\one\two\*\four
name=*.c
I have made a modified version:

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set "filename=c:\one\two\*\four\*.c"

@for %%A in (f_path f_name fname) do set "%%A="
set "f_path=%filename:\=" & set "f_path=!f_path!!f_name!" & set "f_name=\%" & set "f_name=!f_name:~1!" & set "fname=!f_name!" & set "f_name=\"

echo Result:
echo(
echo filename=%filename%
echo path=%f_path%
echo name=%fname%

echo(
echo Debug Version

@for %%A in (f_path f_name fname) do set "%%A="
set "f_path=%filename:\=" & set "f_path=!f_path!!f_name!" & (set f_) & set "f_name=\%" &  (set f_) & set "f_name=!f_name:~1!" & (set f_name) & set "fname=!f_name!" & set "f_name=\"

echo Result:
echo(
echo filename=[%filename%]
echo path=[%f_path%]
echo name=[%fname%]

Output:

Code: Select all

Result:

filename=c:\one\two\*\four\*.c
path=c:\one\two\*\four
name=*.c

Debug Version
f_path=c:
f_name=\one
f_path=c:\one
f_name=\two
f_path=c:\one\two
f_name=\*
f_path=c:\one\two\*
f_name=\four
f_path=c:\one\two\*\four
f_name=\*.c
f_path=c:\one\two\*\four
f_name=*.c
Result:

filename=[c:\one\two\*\four\*.c]
path=[c:\one\two\*\four]
name=[*.c]

Aacini
Expert
Posts: 1920
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Split a filename containing wildcards in path and name without expanding the wildcards

#6 Post by Aacini » 08 Dec 2024 15:21

OJBakker wrote:
07 Dec 2024 03:31
Antonio
Your code gives incorrect output for the path:

Code: Select all

filename=c:\one\two\*\four\*.c
path=c:.c\one\two\*\four
name=*.c
I have made a modified version:

. . . . .
Mmm... My code fail if there is a name variable before the program run, that is, if you remove the setlocal EnableDelayedExpansion command and run the program twice, or if you create a "name" variable entering a set "name=.c" command from the command prompt before run the program (in order to show the result of your example), or if you cancel the program via Ctrl-C after "name" variable was created and before the program end (so the automatic "endlocal" is not executed)...

However, the cure for these "problems" is very simple: just add a set "name=" command before the long replacement line... The fpath variable does not need to be initialized because the first part of the long line does that.

I used to use simple and short variable names in order to keep clearer the code. I didn't use "path" for the path because it is the same as the system variable, although in this case such a point would not had matter (because of the setlocal command). However, I didn't wanted that someone replied me saying that "path" variable should not be used, so I changed it to "fpath".

If you change the name of a variable, you should change it in all instances of such a variable. In your modified version it is not necessary to manage both "f_name" and "fname" variables; you just need to change the last line to echo name=%f_name%. If you do that, you can also remove the two last assignments from the long replacement line. BTW the last assignment, set "f_name=\", have no sense because such a variable will not be used anymore...

If you want to take a closer review of the method used, I invite you to read this topic, but beware! Such a thread is very long and somewaht crazy...

Antonio

OJBakker
Expert
Posts: 93
Joined: 12 Aug 2011 13:57

Re: Split a filename containing wildcards in path and name without expanding the wildcards

#7 Post by OJBakker » 09 Dec 2024 05:31

Antonio
Sorry for the confusion.
You are entirely right.
Somehow the name variable got stuck in my environment and I had not noticed that when I experimented with your code.
So I changed the code to solve a non-existing problem, but in doing so I showed that it can cause problems when a variable is being used without proper initialisation!
I only changed variable names to make it easier to insert the debug line (set f_) unknowing that one of the variables was causing the problem.
It is interesting that setlocal can be circumented this way. I probably had a syntax error that caused the polluted environment.

This code-injection is very compact code and very powerful but every time I see it being used it takes me a while before I fully understand what and how it is doing what it is doing.

Post Reply