171

I need path to the folder that contains cmd file. With %0 I can get the file name. But how to get the folder name?

c:\temp\test.cmd >> test.cmd

P.S. My current directory != folder of the script.

Andreas Fester
  • 36,091
  • 7
  • 95
  • 123
Mike Chaliy
  • 25,801
  • 18
  • 67
  • 105

9 Answers9

348

For the folder name and drive, you can use:

echo %~dp0

You can get a lot more information using different modifiers:

%~I         - expands %I removing any surrounding quotes (")
%~fI        - expands %I to a fully qualified path name
%~dI        - expands %I to a drive letter only
%~pI        - expands %I to a path only
%~nI        - expands %I to a file name only
%~xI        - expands %I to a file extension only
%~sI        - expanded path contains short names only
%~aI        - expands %I to file attributes of file
%~tI        - expands %I to date/time of file
%~zI        - expands %I to size of file

The modifiers can be combined to get compound results:
%~dpI       - expands %I to a drive letter and path only
%~nxI       - expands %I to a file name and extension only
%~fsI       - expands %I to a full path name with short names only

This is a copy paste from the "for /?" command on the prompt.

Related

Top 10 DOS Batch tips (Yes, DOS Batch...) shows batchparams.bat (link to source as a gist):

C:\Temp>batchparams.bat c:\windows\notepad.exe
%~1     =      c:\windows\notepad.exe
%~f1     =      c:\WINDOWS\NOTEPAD.EXE
%~d1     =      c:
%~p1     =      \WINDOWS\
%~n1     =      NOTEPAD
%~x1     =      .EXE
%~s1     =      c:\WINDOWS\NOTEPAD.EXE
%~a1     =      --a------
%~t1     =      08/25/2005 01:50 AM
%~z1     =      17920
%~$PATHATH:1     =
%~dp1     =      c:\WINDOWS\
%~nx1     =      NOTEPAD.EXE
%~dp$PATH:1     =      c:\WINDOWS\
%~ftza1     =      --a------ 08/25/2005 01:50 AM 17920 c:\WINDOWS\NOTEPAD.EXE
starball
  • 20,030
  • 7
  • 43
  • 238
Wadih M.
  • 12,810
  • 7
  • 47
  • 57
  • Cool. Do I need a particular score to modify someone else's wiki post? – Wadih M. Mar 18 '09 at 19:21
  • @Wadih M.: Generally useful link http://stackoverflow.com/questions/18557/how-does-stackoverflow-work-the-unofficial-faq – jfs Mar 18 '09 at 19:26
  • @Wadih M.: In particular http://stackoverflow.com/questions/130654/how-does-reputation-work-on-stackoverflow – jfs Mar 18 '09 at 19:27
  • @Wadih M.: From the above link: "+750 to edit community 'wiki editable' posts" – jfs Mar 18 '09 at 19:27
  • So if you want a cmd script to set the working directory to the location of the script: `cd /d "%~dp0"` (from [stackoverflow.com/questions/4451668](http://stackoverflow.com/questions/4451668/bat-file-to-open-cmd-in-current-directory)) – Nigel Touch Mar 20 '14 at 15:47
  • @Wadih M. Which of these (if any) can be used in a .reg file? I often see `%1` in .reg files, but when I try to use more exotic options they don't work. – ubiquibacon Feb 05 '15 at 17:15
  • That's not working for me, it just prints the code `%~dp0`. What worked for me though is `echo %CD%` – Naguib Ihab Dec 04 '17 at 00:56
61

The accepted answer is helpful, but it isn't immediately obvious how to retrieve a filename from a path if you are NOT using passed in values. I was able to work this out from this thread, but in case others aren't so lucky, here is how it is done:

@echo off
setlocal enabledelayedexpansion enableextensions

set myPath=C:\Somewhere\Somewhere\SomeFile.txt
call :file_name_from_path result !myPath!
echo %result%
goto :eof

:file_name_from_path <resultVar> <pathVar>
(
    set "%~1=%~nx2"
    exit /b
)

:eof
endlocal

Now the :file_name_from_path function can be used anywhere to retrieve the value, not just for passed in arguments. This can be extremely helpful if the arguments can be passed into the file in an indeterminate order or the path isn't passed into the file at all.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • wow, that's amazing! So windows batch files support function inside the same file, how useful! Since when was this possible? – Luke Jan 21 '14 at 08:26
  • Well, I suppose technically it is not a function. Basically, it is a way to fake an external batch file call within the same file, which allows you to use these modifiers if you aren't actually using an external batch file call. I ran across this syntax somewhere and adapted it because it *looks* more like a regular function call, which makes it more intuitive to use. – NightOwl888 Jan 22 '14 at 11:55
  • 2
    I like that you can pass variables both by reference (as is) and by value (surrounded with "!"s). Ok, you probably don't have "local" variables and a call stack... but hey: it's a cmd script after all, it's a big step ahead anyway ;) I agree, partitioning stuff inside a single file is much more handy than splitting it around several files :) – Luke Jan 22 '14 at 16:51
  • 1
    I think "goto :eof" should be "goto eof" .. without the colon.. as it was breaking for me. – A Khudairy Apr 05 '16 at 08:35
  • No, if you do it that way, you will skip the `endlocal` call at the end of the file. The goto is correct. – NightOwl888 Apr 05 '16 at 09:40
  • 2
    See also: https://ss64.com/nt/syntax-args.html - use `%~dp1` for drive and path only. – Andrew Oct 28 '17 at 01:36
  • 3
    @AKhudairy is correct: https://ss64.com/nt/goto.html With the colon the goto skips the endlocal (and anything else you put afterwards, like a pause). Also you need to add `"`s around `!myPath!` if your path has spaces in it (or have the quotes be part of myPath) – Rick Feb 12 '19 at 23:49
  • I had to use `"%myPath%"` when making the call instead – bunkerdive Apr 22 '20 at 14:29
  • if you want the folder use `set "%~1=%~dp1"` instead of `nx2` – CAD bloke May 01 '20 at 03:20
10

In order to assign these to variables, be sure not to add spaces in front or after the equals sign:

set filepath=%~dp1
set filename=%~nx1

Then you should have no issues.

Frank
  • 1,122
  • 9
  • 12
7

In case anyone wants an alternative method...

If it is the last subdirectory in the path, you can use this one-liner:

cd "c:\directory\subdirectory\filename.exe\..\.." && dir /ad /b /s

This would return the following:

c:\directory\subdirectory

The .... drops back to the previous directory. /ad shows only directories /b is a bare format listing /s includes all subdirectories. This is used to get the full path of the directory to print.

Mark
  • 79
  • 1
  • 1
4

I had same problem in my loop where i wanted to extract zip files in the same directory and then delete the zip file. The problem was that 7z requires the output folder, so i had to obtain the folder path of each file. Here is my solution:

FOR /F "usebackq tokens=1" %%i IN (`DIR /S/B *.zip` ) DO (
  7z.exe x %%i -aoa -o%%i\..
) 

%%i was a full filename path and %ii\.. simply returns the parent folder.

hope it helps.

Gico
  • 1,276
  • 2
  • 15
  • 30
  • Quick and dirty. I like that! Never thought that you cold extend a file path with "\.." and end up with the parent folder. – Oliver R. Nov 10 '16 at 17:11
  • This worked for me on Win10: FOR /R "C:\sourceDir" %I IN (*.gz) DO C:\7-Zip64\7z.exe x "%I" -aou -o%I\..\ – aLx13 Jan 23 '18 at 12:50
  • Yes! This gets around the problem that %~dp1 (etc.) only work on %0, %1, %2 etc. – Artelius Oct 02 '19 at 04:49
2

In case the accepted answer by Wadih didn't work for you, try echo %CD%

Naguib Ihab
  • 4,259
  • 7
  • 44
  • 80
  • No. `%CD%` returns the **current working directory** from where you launched the `.cmd` file, and not the directory where the `.cmd` file itself is stored – Andreas Fester Dec 21 '21 at 19:46
0

This was put together with some edited example cmd

@Echo off

Echo ********************************************************
Echo *  ZIP Folder Backup using 7Zip                        *
Echo *  Usage: Source Folder, Destination Drive Letter      *
Echo *  Source Folder will be Zipped to Destination\Backups *
Echo ********************************************************
Echo off

set year=%date:~-4,4%
set month=%date:~-10,2%
set day=%date:~-7,2%
set hour=%time:~-11,2%
set hour=%hour: =0%
set min=%time:~-8,2%

SET /P src=Source Folder to Backup: 
SET source=%src%\*
call :file_name_from_path nam %src%
SET /P destination=Backup Drive Letter:
set zipfilename=%nam%.%year%.%month%.%day%.%hour%%min%.zip
set dest="%destination%:\Backups\%zipfilename%"


set AppExePath="%ProgramFiles(x86)%\7-Zip\7z.exe"
if not exist %AppExePath% set AppExePath="%ProgramFiles%\7-Zip\7z.exe"

if not exist %AppExePath% goto notInstalled

echo Backing up %source% to %dest%

%AppExePath% a -r -tzip %dest% %source%

echo %source% backed up to %dest% is complete!

TIMEOUT 5

exit;

:file_name_from_path <resultVar> <pathVar>
(
    set "%~1=%~nx2"
    exit /b
)


:notInstalled

echo Can not find 7-Zip, please install it from:
echo  http://7-zip.org/

:end
PAUSE
giusti
  • 3,156
  • 3
  • 29
  • 44
0

IMHO the simplest yet most powerful method to get the full path of a file is:

  1. Start Notepad
  2. Copy and Paste the following text: @echo %1 | clip 3
  3. Save the file as "CopyAsPath.bat"

Now you can either

  1. drag a file over that batch or
  2. copy it into your SendTo menu folder (%USERPROFILE%\AppData\Roaming\Microsoft\Windows\SendTo)

Whether you follow the option 1 or the option 2, one millisecond later you can either

  1. "press Ctrl-V" or
  2. use "Right Mouse Click -> Paste"

to paste the full path+filename wherever you want.

Simple, powerful, and without using any external Windows tool.

Giamma Theo
  • 319
  • 2
  • 6
0

For .bat files you may want to use this command:

title %~f0

to put path and filename of the batch script into window title bar.

pbies
  • 666
  • 11
  • 28