98

How can I extract path and filename from a variable?

Setlocal EnableDelayedExpansion
set file=C:\Users\l72rugschiri\Desktop\fs.cfg

I want to do that without using any function or any GOTO. is it possible?

rschirin
  • 1,939
  • 10
  • 34
  • 44
  • 2
    Possible duplicate of [How to split the filename from a full path in batch?](http://stackoverflow.com/questions/9252980/how-to-split-the-filename-from-a-full-path-in-batch) – iTayb Nov 15 '15 at 18:52

5 Answers5

167
@ECHO OFF
SETLOCAL
set file=C:\Users\l72rugschiri\Desktop\fs.cfg
FOR %%i IN ("%file%") DO (
ECHO filedrive=%%~di
ECHO filepath=%%~pi
ECHO filename=%%~ni
ECHO fileextension=%%~xi
)

Not really sure what you mean by no "function"

Obviously, change ECHO to SET to set the variables rather thon ECHOing them...

See for documentation for a full list.


ceztko's test case (for reference)

@ECHO OFF
SETLOCAL
set file="C:\Users\ l72rugschiri\Desktop\fs.cfg"
FOR /F "delims=" %%i IN ("%file%") DO (
ECHO filedrive=%%~di
ECHO filepath=%%~pi
ECHO filename=%%~ni
ECHO fileextension=%%~xi
)

Comment : please see comments.

Magoo
  • 77,302
  • 8
  • 62
  • 84
  • 1
    @meir - true; I've posted a correction. You learn a lot in a couple of years. – Magoo Nov 11 '15 at 08:27
  • @TrivisionZero: No, the quotes are required in the case that the filename or path contains spaces. – Magoo Mar 06 '16 at 01:52
  • @ceztko : Please explain precisely what the inclusion of `/f` does. – Magoo May 04 '18 at 14:45
  • /F Limits the execution of the loop to just one token, as per [documentation](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/for). In my tests it was necessary, apparently because the path passed was enclosed by quotes. In your example it's perfectly safe and it's just more explicit about the fact that the loop will execute just once. – ceztko May 04 '18 at 15:01
  • Sorry, I am reverting the change because I noticed with /F it's not working anymore in case of spaces in the path. Still, I have issues with your code in my use-case (shell extensions). I won't edit anymore and suggest you the fix in my case, if I can find it. – ceztko May 04 '18 at 15:10
  • Ok, I was able to fix my use case. If I don't add `/F "delims="` I'm not able to both fix paths enclosed by quotes and with whitespaces in between. The use case is shown in the paste bin [here](https://pastebin.com/661JwN8d), with your original code it won't work. `"delims="` just replace the default token separators, which accordingly to doc is space and tab. With this further settings, `/F` makes perfectly sense. I suggest you to fix your code this way, since I think this way it's also more meaningful. – ceztko May 04 '18 at 15:47
  • @ceztko: Please don't include links to pastebin as they are almost certain to become invalid. The problem with your code is that you are assigning a *quoted string* as the filename, so the `for` command encounters a *double*-quoted string. If you assign an *unquoted* string (eg `set "file=C:\Users\ l72rugschiri\Desktop\fs.cfg"`) then the original code works as-advertised. Note that the `set "var=value"` format is designed to ensure that the variable does not include trailing whitespace. Where quotes are *required* they can be added simply, whereas it's quite another task to *remove* them. – Magoo May 04 '18 at 16:08
  • @Magoo: yes, your code definitely works in case of unquoted string with whitespaces. My input unfortunately is the quoted string, and I can't change that because it's not on my control. Of course I can preprocess the string but in that case I have to use a similar `FOR` statement with `/F "delims="` and `%%~i`, that will remove the quotes. If I combine with your code I can just skip this preprocess step. – ceztko May 04 '18 at 16:24
  • I've found (under Windows 7) that just removing the quotes around "%file%" in the for-loop expression works irrespective of spaces in the path or filename. So: SET file=%1 FOR %%i IN (%file%) DO ... – Alex T Oct 31 '18 at 16:50
  • @AlexT : Well, it certainly *shouldn't*. Without the quotes, each space/comma/tab-separated part of the string in `file` should be applied to the metavariable `%%i` in turn. If the *value* of `file` **contains** quotes, then the additional quotes are counter-productive, but as explained in the comments above, IMHO it is not a good idea to include quotes in the **value** assigned to a variable as it leads to requiring gymnastics to remove them when required, whereas *adding* quotes is a simple task. YMMV. – Magoo Nov 01 '18 at 06:22
  • Just made a blog post about this using what I learned from your example. Thank you so much for detailing this from Batch Programming. https://garrett.ms/2019/07/03/custom-sendto-execution-shortcuts-windows/ – Cody Jul 03 '19 at 18:51
161

You can only extract path and filename from (1) a parameter of the BAT itself %1, or (2) the parameter of a CALL %1 or (3) a local FOR variable %%a.


in HELP CALL or HELP FOR you may find more detailed information:

%~1 - expands %1 removing any surrounding quotes (")
%~f1 - expands %1 to a fully qualified path name
%~d1 - expands %1 to a drive letter only
%~p1 - expands %1 to a path only
%~n1 - expands %1 to a file name only
%~x1 - expands %1 to a file extension only
%~s1 - expanded path contains short names only
%~a1 - expands %1 to file attributes
%~t1 - expands %1 to date/time of file
%~z1 - expands %1 to size of file


And then try the following:

Either pass the string to be parsed as a parameter to a CALL

call :setfile ..\Desktop\fs.cfg
echo %file% = %filepath% + %filename%
goto :eof

:setfile
set file=%~f1
set filepath=%~dp1
set filename=%~nx1
goto :eof

or the equivalent, pass the filename as a local FOR variable

for %%a in (..\Desktop\fs.cfg) do (
    set file=%%~fa
    set filepath=%%~dpa
    set filename=%%~nxa
)    
echo %file% = %filepath% + %filename%
PA.
  • 28,486
  • 9
  • 71
  • 95
17

All of this works for me:

@Echo Off
Echo Directory = %~dp0
Echo Object Name With Quotations=%0
Echo Object Name Without Quotes=%~0
Echo Bat File Drive = %~d0
Echo Full File Name = %~n0%~x0
Echo File Name Without Extension = %~n0
Echo File Extension = %~x0
Pause>Nul

Output:

Directory = D:\Users\Thejordster135\Desktop\Code\BAT\

Object Name With Quotations="D:\Users\Thejordster135\Desktop\Code\BAT\Path_V2.bat"

Object Name Without Quotes=D:\Users\Thejordster135\Desktop\Code\BAT\Path_V2.bat

Bat File Drive = D:

Full File Name = Path.bat

File Name Without Extension = Path

File Extension = .bat
hd84335
  • 8,815
  • 5
  • 34
  • 45
Thejordster135
  • 171
  • 1
  • 6
3

if you want infos from the actual running batchfile, try this :

@echo off
set myNameFull=%0
echo myNameFull     %myNameFull%
set myNameShort=%~n0
echo myNameShort    %myNameShort%
set myNameLong=%~nx0
echo myNameLong     %myNameLong%
set myPath=%~dp0
echo myPath         %myPath%
set myLogfileWpath=%myPath%%myNameShort%.log
echo myLogfileWpath %myLogfileWpath%

more samples? C:> HELP CALL

%0 = parameter 0 = batchfile %1 = parameter 1 - 1st par. passed to batchfile... so you can try that stuff (e.g. "~dp") between 1st (e.g. "%") and last (e.g. "1") also for parameters

tramper
  • 61
  • 4
1

Late answer, I know, but for me the following script is quite useful - and it answers the question too, hitting two flys with one flag ;-)

The following script expands SendTo in the file explorer's context menu:

@echo off
cls
if "%~dp1"=="" goto Install

REM change drive, then cd to path given and run shell there
%~d1
cd "%~dp1"
cmd /k
goto End

:Install
rem No arguments: Copies itself into SendTo folder
copy "%0" "%appdata%\Microsoft\Windows\SendTo\A - Open in CMD shell.cmd"

:End

If you run this script without any parameters by double-clicking on it, it will copy itself to the SendTo folder and renaming it to "A - Open in CMD shell.cmd". Afterwards it is available in the "SentTo" context menu.

Then, right-click on any file or folder in Windows explorer and select "SendTo > A - Open in CMD shell.cmd"

The script will change drive and path to the path containing the file or folder you have selected and open a command shell with that path - useful for Visual Studio Code, because then you can just type "code ." to run it in the context of your project.

How does it work?

%0 - full path of the batch script
%~d1 - the drive contained in the first argument (e.g. "C:")
%~dp1 - the path contained in the first argument
cmd /k - opens a command shell which stays open

Not used here, but %~n1 is the file name of the first argument.

I hope this is helpful for someone.

Matt
  • 25,467
  • 18
  • 120
  • 187