376

Firstly, I saw this topic but I couldn't understand that.

Question :

There is a batch file in D:\path\to\file.bat with following content :

echo %cd%
pause

Output is :

C:\

It must be D:\path\to

What am I doing wrong?

Community
  • 1
  • 1
Hamed Kamrava
  • 12,359
  • 34
  • 87
  • 125
  • 10
    You should read all the answers to a question, especially the higher vote getters, not just the accepted one. The answer with the highest score at your posted link already answers your question. – dbenham Jun 12 '13 at 11:24
  • 4
    If you are in c:\ when you type the batch file name then c:\ is what %cd% will print. – foxidrive Jun 12 '13 at 12:31

4 Answers4

627

System read-only variable %CD% keeps the path of the caller of the batch, not the batch file location.

You can get the name of the batch script itself as typed by the user with %0 (e.g. scripts\mybatch.bat). Parameter extensions can be applied to this so %~dp0 will return the Drive and Path to the batch script (e.g. W:\scripts\) and %~f0 will return the full pathname (e.g. W:\scripts\mybatch.cmd).

You can refer to other files in the same folder as the batch script by using this syntax:

CALL %0\..\SecondBatch.cmd

This can even be used in a subroutine, Echo %0 will give the call label but, echo "%~nx0" will give you the filename of the batch script.

When the %0 variable is expanded, the result is enclosed in quotation marks.

More on batch parameters.

Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
Stoleg
  • 8,972
  • 1
  • 21
  • 28
  • 1
    Look, I do not need to run `stm.sql` in `D:\Dir1\Dir2\stm.sql`. I need `mysql.exe -u root -p mysql < %cd%\stm.sql` to execute that stm.sql commands. – Hamed Kamrava Jun 12 '13 at 11:32
  • @HamedKamrava is it for my SQL batch? not batch file like `*.bat` or `*.sh`? – Stoleg Jun 12 '13 at 11:34
  • @Stoleg- In fact, There are 2 files in `D:\Dir1\Dir2\batchfile.bat` and `D:\Dir1\Dir2\stm.sql`. batchfile.bat content is : `mysql.exe -u root -p mysql < D:\Dir1\Dir2\stm.sql` and stm.sql content is some MySQL commands. – Hamed Kamrava Jun 12 '13 at 11:41
  • In order to see the path, from which your batch-file is running use `echo %0`. – Stoleg Jun 12 '13 at 11:44
  • @stoleg- I know `echo %0` show batch-file full path but need this `D:\Dir1\Dir2\` no this `D:\Dir1\Dir2\batchfile.bat` – Hamed Kamrava Jun 12 '13 at 11:49
  • 1
    System read-only variable %CD% keep the path of the caller of the batch, not the batch file location. – Stoleg Jun 12 '13 at 11:50
  • As i showed in the first post i need batch-file location. But how ? – Hamed Kamrava Jun 12 '13 at 11:55
  • 56
    `echo %~dp0` will return path to batch location. `echo %~f0` will return path to the batch with filename. – Stoleg Jun 12 '13 at 12:03
163

Very simple:

setlocal
cd /d %~dp0
File.exe
Pokechu22
  • 4,984
  • 9
  • 37
  • 62
shay
  • 2,021
  • 1
  • 15
  • 17
  • 21
    The code is short but it is not simple to understand. What is this File.exe? Is the current directory path stored in %~dp0 ? – Ivailo Bardarov May 05 '17 at 10:06
  • This answer actually answers the question, I think. Kudos. – macetw Oct 04 '17 at 23:14
  • 5
    I just used `cd /d %~dp0` as first line of batch file and worked – mkb Oct 25 '17 at 04:03
  • why need setlocal? it returns well without that too? – T.Todua Apr 13 '18 at 09:39
  • 3
    @T.Todua "setlocal" causes any environment changes, including current directory to be contained either until the batch file ends or a "endlocal" is encountered. If you're going to change environment variables or the current directory, it's good form. – Jamie May 25 '18 at 17:28
  • 5
    Best to use `"%~dp0"` rather than `%~dp0`. Quotes will guarantee the path is taken as one token, even if there are spaces, and also protects against poison characters like `&`. – dbenham Dec 20 '19 at 03:53
  • @dbenham The answer should be edited then – endolith Jan 22 '21 at 18:36
  • 1
    When you use ~ in the variable that indicate a path, it allows us to extract specific part of the path, d is for drive, p is for path, n is for name and x is for extension. Example, assuming the below lines in c:\temp\myfile.bat echo off echo %0 echo %~n0 echo %~x0 echo %~d0 echo %~p0 echo on will print: c:\temp\myfile.bat myfile .bat c: \temp\ – Pramod B R Jul 20 '21 at 12:02
46

Within your .bat file:

set mypath=%cd%

You can now use the variable %mypath% to reference the file path to the .bat file. To verify the path is correct:

@echo %mypath%

For example, a file called DIR.bat with the following contents

set mypath=%cd%
@echo %mypath%
Pause

run from the directory g:\test\bat will echo that path in the DOS command window.

jeb
  • 78,592
  • 17
  • 171
  • 225
rockerron
  • 589
  • 4
  • 2
17

Here's what I use at the top of all my batch files. I just copy/paste from my template folder.

@echo off
:: --HAS ENDING BACKSLASH
set batdir=%~dp0
:: --MISSING ENDING BACKSLASH
:: set batdir=%CD%
pushd "%batdir%"

Setting current batch file's path to %batdir% allows you to call it in subsequent stmts in current batch file, regardless of where this batch file changes to. Using PUSHD allows you to use POPD to quickly set this batch file's path to original %batdir%. Remember, if using %batdir%ExtraDir or %batdir%\ExtraDir (depending on which version used above, ending backslash or not) you will need to enclose the entire string in double quotes if path has spaces (i.e. "%batdir%ExtraDir"). You can always use PUSHD %~dp0. [https: // ss64.com/ nt/ syntax-args .html] has more on (%~) parameters.

Note that using (::) at beginning of a line makes it a comment line. More importantly, using :: allows you to include redirectors, pipes, special chars (i.e. < > | etc) in that comment.

:: ORIG STMT WAS: dir *.* | find /v "1917" > outfile.txt

Of course, Powershell does this and lots more.

Wendell Holmes
  • 181
  • 1
  • 2
  • 4
    Great answer, thanks a lot! :-) **Just beware your second technique (`set batdir=%CD%`).** It is not okay, because it is the path to the caller, not the bat file itself. The only valid way to get the path to the executing bat file is `%~dp0`. – Mitch McMabers Oct 14 '19 at 04:31