I have search the web high and low, but can not find away to copy a file to the desktop with a command line.
Xcopy File.exe c:/users/%username%/desktop
This gives me a error like
Access denied
I look in to robocopy also, with no luck.
Is there another program i can use?
Ps. I also tested
takeown /f <foldername> /r /d y
We use backslashes for paths. Forward slash is switch and backslash is path separator.
Use %userprofile%\desktop. If the path is likely to have spaces enclose in quotes.
copy c:\windows\win.ini "%userprofile%\desktop\*.*"
Reference
& seperates commands on a line.
&& executes this command only if previous command's errorlevel is 0.
|| (not used above) executes this command only if previous command's errorlevel is NOT 0
> output to a file
>> append output to a file
< input from a file
| output of one command into the input of another command
^ escapes any of the above, including itself, if needed to be passed to a program
" parameters with spaces must be enclosed in quotes
+ used with copy to concatinate files. E.G. copy file1+file2 newfile
, used with copy to indicate missing parameters. This updates the files modified date. E.G. copy /b file1,,
%variablename% a inbuilt or user set environmental variable
!variablename! a user set environmental variable expanded at execution time, turned with SelLocal EnableDelayedExpansion command
%<number> (%1) the nth command line parameter passed to a batch file. %0 is the batchfile's name.
%* (%*) the entire command line.
%<a letter> or %%<a letter> (%A or %%A) the variable in a for loop. Single % sign at command prompt and double % sign in a batch file.
\\ (\\servername\sharename\folder\file.ext) access files and folders via UNC naming.
: (win.ini:streamname) accesses an alternative steam. Also separates drive from rest of path.
. (win.ini) the LAST dot in a file path seperates the name from extension
. (dir .\*.txt) the current directory
.. (cd ..) the parent directory
\\?\ (\\?\c:\windows\win.ini) When a file path is prefixed with \\?\ filename checks are turned off.
< > : " / \ | Reserved characters. May not be used in filenames.
Reserved names. These refer to devices eg,
copy filename con
which copies a file to the console window.
CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4,
COM5, COM6, COM7, COM8, COM9, LPT1, LPT2,
LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9
Maximum path length 260 characters
Maximum path length (\\?\) 32,767 characters (approx - some rare characters use 2 characters of storage)
Maximum filename length 255 characters
.
--
Related
I wrote a batch script for my development environment variables, but have some troubles because I'm not familiar with Windows batch scripts.
This is what I tried so far:
echo window._env_ = { > ./env-config.js
findstr /v # .env >> ./env-config.js
echo } >> ./env-config.js
It outputs this:
window._env_ = {
REACT_APP_SITE_TITLE=MyWebsite
REACT_APP_SITE_URL=http://localhost:3000
BROWSER=none
REACT_APP_API_ENDPOINT=http://localhost:5000
}
These are the environment variables stored in the file .env which I want to write into the file env-config.js:
#
# Website Title
REACT_APP_SITE_TITLE=MyWebsite
#
# Website URL
REACT_APP_SITE_URL=https://my-website-url.org
#
# Define if the Browser auto-open at react start
BROWSER=none
#
# Define the API Endpoint for the Backend
REACT_APP_API_ENDPOINT=http://localhost:5000
The final env-config.js should look like this:
window._env_ = {
REACT_APP_SITE_TITLE: "MyWebsite",
REACT_APP_SITE_URL: "https://my-website-url.org",
BROWSER: "none",
REACT_APP_API_ENDPOINT: "http://localhost:5000",
}
So what I need to do is to set the variable values in the output in quotes, change = to : and add a comma at the end. But I can´t find a solution combined with findstr.
Does anyone have an idea how to get the wanted output from the input?
FINDSTR outputs all lines containing a searched string or a string matched by a regular expression respectively with the usage of option /V all lines NOT containing a searched string or a string matched by a regular expression (inverted result). Therefore FINDSTR can be used to filter out the lines starting with #, but the other lines are output as stored in the file .env which is of no help here as the lines not starting with # should be written reformatted into the file env-config.js.
The solution is using a FOR /F loop to process each line in the text file .env and output the lines not starting with # with command ECHO with the values of interest reformatted as required redirected into the file env-config.js.
The batch file solution with just a single command line:
#(echo window._env_ = {& (for /F "eol=# tokens=1* delims==" %%I in (.env) do #echo %%I: "%%J",) & echo })> .\env-config.js
# at beginning of a command line executed just once (everything after first #) or multiple times (echo %%I: "%%J", inside the loop) during the batch file execution prevents the output of the command line after parsing and before executing it. Batch files contain usually at top #echo off to turn off command echo mode for all further command lines in the batch file and prevent also the output of this first command line.
The opening round bracket ( after first # defines a command block which ends with the last closing parenthesis ) left to redirection operator >. The Windows Command Processor cmd.exe processing the batch file opens first the file env-config.js in the current directory as defined with the relative path .\ for write operations and truncates the file to zero length if that file exists already because of everything output to handle STDOUT (standard output) during execution of the command block should be redirected into this file. The file is kept open until the execution of all commands inside the command block finished.
The ampersand & outside a double quoted argument string is interpreted as unconditional AND command operator. For more details about unconditional and conditional (&& and ||) command operators see single line with multiple commands using Windows batch file.
The command block on a single command line contains here three commands which are executed once.
ECHO is different to most other Windows commands as it does not interpret a space character as argument string separator, but as character to output. For that reason there is no space between { and & to avoid that this space is output by ECHO resulting in a trailing space in the file env-config.js.
Which commands are executed can be seen easier by splitting the single command line version up into multiple command lines.
#echo off
(
echo window._env_ = {
for /F "eol=# tokens=1* delims==" %%I in (.env) do echo %%I: "%%J",
echo }
)> .\env-config.js
The inner command block defined by ( left to for and ending with ) after , is not needed anymore in this case because of the line termination defines where the FOR command line executing multiple times the command ECHO ends. In the single command line version the two round brackets are needed to let cmd know where the command line to execute by FOR on each loop iteration ends.
There is first written into the opened file env-config.js the string window._env_ = { output by command ECHO with carriage return and line-feed as line termination (18 characters/bytes).
Next the file .env in current directory is opened for read operations because of option /F of command FOR and the file name .env neither enclosed in " (processing of string) nor in ' (processing of captured output of a command line).
The default behavior of FOR /F on processing the lines of a text file is
ignoring empty lines which are lines not containing any character than the line ending characters carriage return and line-feed,
splitting the line up into substrings using normal space and horizontal tab as string delimiters with removal of all leading spaces/tabs from the line,
looking on first character of first substring on being a semicolon which is the default end of line character in which case the line is not further processed,
assigning the first space/tab delimited substring not starting with ; to the specified loop variable and
executing the command respectively the commands in the command block specified after do.
This line splitting behavior is modified with the options eol=# tokens=1* delims== specified within " to be interpreted as one argument string after option /F to
split up each non-empty line on equal signs as defined with delims==,
ignore all lines starting with the character # as defined with eol=#,
whereby two substrings are wanted, the first substring and everything after the equal sign(s) after first substring kept as is without splitting this part of the line up further on equal signs as defined with tokens=1* and
assign the first equal sign delimited substring to specified loop variable I and if there is something more on the line to the next loop variable J according to ASCII table.
So the lines starting with # in file .env are ignored and on other lines the string left to first (series of) = is assigned to the loop variable I (name) and everything after first (series of) = is assigned to the loop variable J (value) which can be also an empty string if there is nothing after first equal sign.
The two strings are output with command ECHO with a colon and a space between name and value and with enclosing the value in double quotes and with a comma at end of the line and this output is written with carriage return and line-feed into the opened file env-config.js.
Last after all lines of .env are processed by FOR /F and this file is closed, there is output with ECHO the string } with the newline characters carriage return and line-feed.
The execution of all commands of the command block is finished with echo } and so cmd closes the file env-config.js containing now all the output characters/bytes.
The current directory is not necessarily the directory containing the batch file. So if it is expected that the file .env is in the directory of the batch file and the file env-config.js should be created also in the directory of the batch file, it would be better to use the following single command line batch file.
#(echo window._env_ = {& (for /F "usebackq eol=# tokens=1* delims==" %%I in ("%~dp0.env") do #echo %%I: "%%J",) & echo })> "%~dp0env-config.js"
The multi-line version is:
#echo off
(
echo window._env_ = {
for /F "usebackq eol=# tokens=1* delims==" %%I in ("%~dp0.env") do echo %%I: "%%J",
echo }
)> "%~dp0env-config.js"
%~dp0 (drive and path of batch file argument 0) expands to the full directory path of the batch file always ending with a backslash and therefore concatenated without one more \ with the file names .env and env-config.js.
The FOR /F option usebackq is used additionally to get the fully qualified file name of the file .env in the batch file directory enclosed in " interpreted as file name of a text file of which lines to process and not as string to process.
Please note that the directory separator on Windows is \ and not / as on Linux/Mac as described by Microsoft in the documentation about Naming Files, Paths, and Namespaces. The usage of / instead of \ in file/folder strings usually work thanks to the automatic correction applied by the Windows I/O functions as explained by the referenced Microsoft documentation page. But there are use cases on which the usage of / in a file/folder string results in unexpected behavior as described with two examples in the answer on How can I check if either or file exists in IF Exist?
For completeness a multi-line batch file which outputs the lines in file .env in directory of the batch file into the file env-config.js in directory of the batch file without a comma on the last line read from .env.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FirstLine=1"
(
echo window._env_ = {
for /F "usebackq eol=# tokens=1* delims==" %%I in ("%~dp0.env") do (
if not defined FirstLine (echo ,) else set "FirstLine="
set /P =%%I: "%%J"<nul
)
echo(
echo }
)> "%~dp0env-config.js"
endlocal
There can be removed both %~dp0 to use the current directory instead of the batch file directory.
The IF condition results in the output of a string with a comma, a carriage return and a line-feed if the currently processed line is not the first line with data to output read from the file .env.
The command SET with option /P is used here with no environment variable name to output the reformatted data to handle STDOUT without a carriage return and line-feed which does not wait for user input because of the device NUL is used as STDIN (standard input) which cannot be opened to read something.
The additional command line echo( results in the output of just carriage return and line-feed to terminate also the last line with data read from .env not having a comma at end.
These are special "hacks" not officially documented by Microsoft, but documented in many answers on Stack Overflow and in DosTips forum topics ECHO. FAILS to give text or blank line - Instead use ECHO/
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /? ... explains batch file argument referencing as done with %~dp0
echo /?
endlocal /?
for /?
if /?
set /?
setlocal /?
See also the Microsoft documentation about Using command redirection operators.
This question already has answers here:
Variables are not behaving as expected
(1 answer)
Example of delayed expansion in batch file
(5 answers)
At which point does `for` or `for /R` enumerate the directory (tree)?
(1 answer)
Closed 1 year ago.
I'm trying to write a batch script that'll read all the pdf files in a folder and rename them such that there are no spaces in them. So I've typed up the below code. Although most of the parts of the code seems to work in isolation, I get an error when running the code together.
for /r %%f in (*.txt) do (
set filename=%%~nxf
set new=%filename: =%
ren "%filename%" %new%
)
The filename is detected correctly by line2. But on line3, I don't get the value I've stored in line2. Interestingly enough, if I were to run the command again in the same prompt, line3 then works (filename variable is read correctly). It must be how the for loop operates in a batch script. If I run the below code exactly 3 times in the same command prompt, the code works perfectly fine (I assume because all variables are now set correctly). Can someone please help point me in the right direction? Thanks in advance.
Note: I have a filename called "filename .txt" in the working directory, which I realise wasn't the best choice of filename. :|
(error in screenshot)
Open a command prompt, run set /? and read the output help carefully and completely from top of first to bottom of last page, especially the section about delayed expansion explained also by Variables are not behaving as expected. The Windows command processor cmd.exe processes the entire command block starting with ( and ending with matching ) before executing command FOR at all. All environment variables using %...% syntax are expanded (replaced) already during this processing phase by the appropriate variable expansion result.
So executed is the following on environment variable filename not already defined:
for /R %f in (*.txt) do (
set filename=%~nxf
set new= =
ren ""
)
That can be seen on debugging the batch file by running it from within a command prompt window instead of double clicking the batch file. This results in the following error message for each *.txt file found in current directory and all its subdirectories:
The syntax of the command is incorrect.
The syntax of the command ren is of course incorrect.
One solution is using following batch code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "delims=" %%I in ('dir "* *.txt" /A-D /B /S 2^>nul') do (
set "FullName=%%I"
set "FileName=%%~nxI"
setlocal EnableDelayedExpansion
ren "!FullName!" "!FileName: =!"
endlocal
)
endlocal
The first two lines define completely the required execution environment for the batch file.
There is not used a for /R loop as that can cause troubles depending on file system of current drive and the file names to modify on renaming the files with file extension .txt while the FOR loop iterates of the file system entries matching the wildcard pattern.
The usage of the for /F loop results in first starting one more command process in background with %ComSpec% /c and the specified command line appended as additional arguments. So with Windows installed in C:\Windows is executed in background:
C:\Windows\System32\cmd.exe /C dir "* *.txt" /A-D /B /S 2>nul
The second command process runs DIR which
searches in current directory and all its subdirectories because of option /S
for just files because of option /A-D (attribute not directory)
of which name matches the wildcard pattern * *.txt in long or short name
and outputs the found file names in bare format because of option /B which means just the file names with full path because of option /S.
The command DIR finds also matching file names of files with hidden attribute set which are ignored by for /R. The option /A-D could be modified to /A-D-H to ignore hidden files.
The wildcard pattern contains a space character. For that reason the command DIR outputs just the full qualified file names of files which contain at least one space character in long file name. Short 8.3 file names cannot contain a space character.
The error message output by DIR if it cannot find at least one file name matching the wildcard pattern in the entire directory tree of current directory is suppressed by redirecting the error message from handle STDERR to device NUL.
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
The command FOR respectively the cmd.exe instance processing the batch file captures all lines output by DIR to handle STDOUT of command process started in background. The processing of the list of full qualified file names starts when started cmd.exe closed itself after finishing execution of command DIR.
The list of file names to process is now completely in memory of the command process executing the batch file. The file renames done next by the loop cause multiply changes in file system, but that does not affect the list of file names processed by FOR as it is the case on using for /R. So there is surely no file name with a space in name skipped as the file system changes do not affect the processing of the files to rename.
FOR with option /F results by default in ignoring all empty lines. The command DIR does not output empty lines.
Next a non-empty line is split up by default into substrings using horizontal tab and normal space as string delimiters. That string splitting behavior is definitely not wanted here as the files to rename contain at least one space character. For that reason delims= is used to define an empty list of string delimiters which turns off the line splitting behavior completely.
There is by default ignored next a line of which first substring starts with default end of line character ;. But the command DIR with option /S outputs all file names with full path and it is therefore impossible that any full qualified file name starts with a semicolon. So it is not necessary to modify the default end of line character.
The full file name is assigned to loop variable I which is next assigned to the environment variable FullName. The file name with file extension without path is assigned to environment variable FileName. The environment variables are (re)defined while delayed environment variable expansion is disabled to process also file names correct containing one or more ! in name. If delayed expansion would be already enabled, each exclamation mark in file name assigned to loop variable I would be interpreted as beginning/end of a delayed expanded environment variable reference which of course is not wanted in this case.
Now delayed expansion is enabled to be able to rename the file using its full file name referenced delayed expanded and its new name without path with all spaces removed. Then the previous environment is restored which is necessary to avoid a stack overflow as there is much more done in background by setlocal EnableDelayedExpansion than toggling the state of delayed expansion and to process the next file name again in an environment with delayed expansion disabled. See this answer for details on what happens in background on each usage of the commands SETLOCAL and ENDLOCAL.
There is no guarantee that each file rename really works. The file rename fails if there is already a file or directory with new name in the directory of a file to rename. A file rename fails also if a file to rename is currently opened by an application which opened it with denying any access by another application.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
dir /?
echo /?
endlocal /?
for /?
ren /?
set /?
setlocal /?
I have a folder with many sub-folders which have further sub-folders. each folder has a number of files.
I want to rename all the file by adding some suffix to them
for ex:
Original: FileName1.ext
Final : Suf_FileName1.ext
To carry out this function, found this command online
`FOR /R %x IN (*) DO ren "%x" Suf_*`
but this replaces the initial characters in the original file name
like
Original: FileName1.ext
Final : Suf_Name.ext
(please note it has removed initial characters in the initial file name )
Please suggest changes/modifications in the above command,
or another command to carry out the function.
Thanks in Advance.
When you use a for command to iterate over a set of files, the for replaceable parameter (%x in your sample) contains a reference to the file.
When you use %x in the commands contained in the do clause, this parameter is replaced by information of the file being processed, by default the name and extension of the file (when using a simple for) or the file with full path (when using a recursive for /R), but you can decide and changee what information you want to use. The replaceable parameter allows the usage of some modifiers (you can see the full list if you execute for /?)
In your case, for your rename mask you need the name and extension of the file being referenced (I've changed your %x with %F so the syntax is clearer)
%~nxF
^^^^.... replaceable parameter
||+..... extension of the file referenced
|+...... name of the file referenced
+....... operator for modifier usage
Your command could be something like
for /R %F in (*) do echo ren "%F" "Suf_%~nxF"
note: The echo in the command is just a debugging habit. Before changing anything, first show to console the commands that will be executed. If the output seems correct then we only have to remove the echo and run the command again.
Remember that if you want to use the command inside a batch file, you need to escape the percent signs in the for replaceable parameters by doubling them. Inside a batch file the previous command will be
for /R %%F in (*) do echo ren "%%F" "Suf_%%~nxF"
So I'm trying to set up a template file structure for projects that can be modified in name to suit each project. I have created the example directory containing example folders i.e. "Template project" contains "template hardware" , "template software" etc. , and have a simple batch program that copies the "template project" folder and all contained subfolders, however I would like to change the word 'template' with what ever I choose to call the project. I was wondering if this is possible to do? Ideally I could just edit the batch file with the name of the project and then run it to copy the template and rename it.
Any help is greatly appreciated!
To start learning type help at the command prompt. Then anything on that list add /? for more help.
Set /p NewName=Enter project name
md "c:\somewhere\%newname%project\%newname% software
md "c:\somewhere\%newname%project\%newname% hardware
or use xcopy (and use/l to have it do a test without copying)
xcopy "c:\tempate" "d:\%newname%" /e /h /q /i /c
See set /?, md /?, and xcopy /?. Type just set to see a list of variables.
& seperates commands on a line.
&& executes this command only if previous command's errorlevel is 0.
|| (not used above) executes this command only if previous command's errorlevel is NOT 0
> output to a file
>> append output to a file
< input from a file
| output of one command into the input of another command
^ escapes any of the above, including itself, if needed to be passed to a program
" parameters with spaces must be enclosed in quotes
+ used with copy to concatinate files. E.G. copy file1+file2 newfile
, used with copy to indicate missing parameters. This updates the files modified date. E.G. copy /b file1,,
%variablename% a inbuilt or user set environmental variable
!variablename! a user set environmental variable expanded at execution time, turned with SelLocal EnableDelayedExpansion command
%<number> (%1) the nth command line parameter passed to a batch file. %0 is the batchfile's name.
%* (%*) the entire command line.
%<a letter> or %%<a letter> (%A or %%A) the variable in a for loop. Single % sign at command prompt and double % sign in a batch file.
\\ (\\servername\sharename\folder\file.ext) access files and folders via UNC naming.
: (win.ini:streamname) accesses an alternative steam. Also separates drive from rest of path.
. (win.ini) the LAST dot in a file path seperates the name from extension
. (dir .\*.txt) the current directory
.. (cd ..) the parent directory
\\?\ (\\?\c:\windows\win.ini) When a file path is prefixed with \\?\ filename checks are turned off.
< > : " / \ | Reserved characters. May not be used in filenames.
Reserved names. These refer to devices eg,
copy filename con
which copies a file to the console window.
CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4,
COM5, COM6, COM7, COM8, COM9, LPT1, LPT2,
LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9
CONIN$, CONOUT$, CONERR$
Maximum path length 260 characters
Maximum path length (\\?\) 32,767 characters (approx - some rare characters use 2 characters of storage)
Maximum filename length 255 characters
Starting a Program
===============
See start /? and call /? for help on all three ways.
Specify a program name
--------------------------------
c:\windows\notepad.exe
In a batch file the batch will wait for the program to exit. When
typed the command prompt does not wait for graphical
programs to exit.
If the program is a batch file control is transferred and the rest of the calling batch file is not executed.
Use Start command
--------------------------
start "" c:\windows\notepad.exe
Start starts a program and does not wait. Console programs start in a new window. Using the /b switch forces console programs into the same window, which negates the main purpose of Start.
Start uses the Windows graphical shell - same as typing in WinKey + R (Run dialog). Try
start shell:cache
Use Call command
-------------------------
Call is used to start batch files and wait for them to exit and continue the current batch file.
.
--
I'm looking at a batch file which defines the following variables:
set _SCRIPT_DRIVE=%~d0
set _SCRIPT_PATH=%~p0
What do %~d0 or %~p0 actually mean?
Is there a set of well-known values for things like current directory, drive, parameters to a script?
Are there any other similar shortcuts I could use?
The magic variables %n contains the arguments used to invoke the file: %0 is the path to the bat-file itself, %1 is the first argument after, %2 is the second and so on.
Since the arguments are often file paths, there is some additional syntax to extract parts of the path. ~d is drive, ~p is the path (without drive), ~n is the file name. They can be combined so ~dp is drive+path.
%~dp0 is therefore pretty useful in a bat: it is the folder in which the executing bat file resides.
You can also get other kinds of meta info about the file: ~t is the timestamp, ~z is the size.
Look here for a reference for all command line commands. The tilde-magic codes are described under for.
They are enhanced variable substitutions. They modify the %N variables used in batch files. Quite useful if you're into batch programming in Windows.
%~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
%~$PATH:I - searches the directories listed in the PATH
environment variable and expands %I to the
fully qualified name of the first one found.
If the environment variable name is not
defined or the file is not found by the
search, then this modifier expands to the
empty string
You can find the above by running FOR /?.
Yes, There are other shortcuts that you can use which are given below.
In your command, ~d0 would mean the drive letter of the 0th argument.
~ expands the given variable
d gets the drive letter only
0 is the argument you are referencing
As the 0th argument is the script path, it gets the drive letter of the path for you. You can use the following shortcuts too.
%~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
%~$PATH:1 - searches the directories listed in the PATH
environment variable and expands %1 to the fully
qualified name of the first one found. If the
environment variable name is not defined or the
file is not found by the search, then this
modifier expands to the empty string
%~dp1 - expands %1 to a drive letter and path only
%~nx1 - expands %1 to a file name and extension only
%~dp$PATH:1 - searches the directories listed in the PATH
environment variable for %1 and expands to the
drive letter and path of the first one found.
%~ftza1 - expands %1 to a DIR like output line
This can be also found directly in command prompt when you run CALL /? or FOR /?
From Filename parsing in batch file and more idioms - Real's How-to:
The path (without drive) where the script is : ~p0
The drive where the script is : ~d0
Another tip that would help a lot is that to set the current directory to a different drive one would have to use %~d0 first, then cd %~dp0. This will change the directory to the batch file's drive, then change to its folder.
For #oneLinerLovers, cd /d %~dp0 will change both the drive and directory :)
Hope this helps someone.
Some gotchas to watch out for:
If you double-click the batch file %0 will be surrounded by quotes. For example, if you save this file as c:\test.bat:
#echo %0
#pause
Double-clicking it will open a new command prompt with output:
"C:\test.bat"
But if you first open a command prompt and call it directly from that command prompt, %0 will refer to whatever you've typed. If you type test.batEnter, the output of %0 will have no quotes because you typed no quotes:
c:\>test.bat
test.bat
If you type testEnter, the output of %0 will have no extension too, because you typed no extension:
c:\>test
test
Same for tEsTEnter:
c:\>tEsT
tEsT
If you type "test"Enter, the output of %0 will have quotes (since you typed them) but no extension:
c:\>"test"
"test"
Lastly, if you type "C:\test.bat", the output would be exactly as though you've double clicked it:
c:\>"C:\test.bat"
"C:\test.bat"
Note that these are not all the possible values %0 can be because you can call the script from other folders:
c:\some_folder>/../teST.bAt
/../teST.bAt
All the examples shown above will also affect %~0, because the output of %~0 is simply the output of %0 minus quotes (if any).
%~d0 gives you the drive letter of argument 0 (the script name), %~p0 the path.
This code explains the use of the ~tilde character, which was the most confusing thing to me. Once I understood this, it makes things much easier to understand:
#ECHO off
SET "PATH=%~dp0;%PATH%"
ECHO %PATH%
ECHO.
CALL :testargs "these are days" "when the brave endure"
GOTO :pauseit
:testargs
SET ARGS=%~1;%~2;%1;%2
ECHO %ARGS%
ECHO.
exit /B 0
:pauseit
pause
It displays the current location of the file or directory that you are currently in. for example; if your batch file was in the desktop directory, then "%~dp0" would display the desktop directory. if you wanted it to display the current directory with the current file name you could type "%~dp0%~n0%~x0".