Windows batch file starting directory when 'run as admin' - windows

I have a batch file which is in a directory and must be run from there as well because it updates files within this directory.
This works perfectly fine, except when the user runs the batch file as administrator (required on Vista). Then the starting directory is C:\Windows\System32.
Is there any way to still be able to know from which directory the batch file was run?
I dont want the user to enter the directory manually.

Try to access the batch files path like this:
echo %~dp0
For more information see the following quote from the command for /? that describes how the above command works:
You can now use the following optional syntax:
%~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
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
%~dp$PATH:I - searches the directories listed in the PATH
environment variable for %I and expands to the
drive letter and path of the first one found.
%~ftzaI - expands %I to a DIR like output line

Better than cd is pushd which will
change drive letter if starting from D:\...
assign a drive letter if on a UNC network path
So pushd %~dp0 is good.
Good practice is then to call popd when done.

This should solve your problem by setting the working directory for the batch file back to the current directory:
Include these two lines at the top of your .bat script:
#setlocal enableextensions
#cd /d "%~dp0"
Found at: http://www.codeproject.com/Tips/119828/Running-a-bat-file-as-administrator-Correcting-cur

To fix this problem, include these two lines at the top of your .bat script:
#setlocal enableextensions
#cd /d "%~dp0"

I use:
cd %0..
at the beginning of the batch file to change directory to the directory where the batch file was started in.
-Mathew

#setlocal enableextensions
#cd /d "%~dp0"

You can CD directly from the file name by adding the parent (not tested in windows 8.x, but has worked "forever" as far as I can remember).
CD %FILENAME%\..
and CD will change drives as well using /D, which is shown above but not explicitly mentioned so might be missed.
CD /D %FILENAME%\..
(FOR /?
IF /?
SET /?
CALL /?
GOTO /?
all provide highly useful reading if you use cmd.exe, I reread them once in a while.)

A working solution here:
http://www.vistax64.com/vista-general/79849-run-administrator-changes-default-directory.html
FOR /F %%I IN ("%0") DO SET BATDIR=%%~dpI
ECHO The batch file is located in directory %BATDIR%

Related

CMD error filename/directory error

I used to program batch files for work but I quit since a long time, now I'm back on the job and there seemed to be a bit of a problem.
I try to edit txt files using CMD commands on a batch file:
e.g. echo hello >> *.txt
the thing is I want to add the text to all the txt files in that directory and I remember the * represented all the files in that directory with the same extension unless it's used as *.* then it includes all the files, but now all it does is just writes this error on cmd:
The filename, directory name, or volume label syntax is incorrect.
Can anyone can give a little help?
You can use a FOR /F loop with a DIR command to iterate the full paths and pass those over to the redirection append >> to echo to the text files accordingly.
Example FOR Loop
Be sure to change the value of the Folder= variable to be the directory you need to append to the files with the ECHO command.
Confirmed working batch script example
#ECHO ON
SET Folder=C:\MyFolder
CD /D "%Folder%"
FOR /F "TOKENS=*" %%A IN ('DIR /B /A-D "%Folder%\*.txt"') DO ECHO HELLO>>%%~fA
PAUSE
EXIT
Further Resources
DIR
FOR /F
In addition, substitution of FOR variable references has been
enhanced. You can now use the following optional syntax:
%~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

Simple Windows batch to move folders

I'm simply trying to move all files and subdirectories inside d:\temp\test to d:\temp\archive and so I tried these commands:
move d:\temp\test\* d:\temp\archive\
move d:\temp\test\*.* d:\temp\archive\
but I got this error in return:
The filename, directory name, or volume label syntax is incorrect.
Then I dug around on the web and tried this inside a doc bat:
for %%F in ( d:\temp\test\*.* ) do move /Y %%F d:\temp\archive
and this time it shows no error, but everything is standing still and made no changes.
What am i missing here? I'm trying this on Windows 10.
ok, if you want to just move all the files directories from inside \test\ then this will do the files first, then directories in a batch. The for /d will copy the directories and sub directories and files.
#echo off
move "d:\temp\test\*" "d:\temp\archive"
for /d %%a in ("D:\temp\test\*") do move "%%~fa" "d:\temp\archive\"
as a side note, from cmd when running below you get an error.
move d:\temp\test\* d:\temp\archive
That is because it will move all files, but not directories. If you get The filename, directory name, or volume label syntax is incorrect. there are no files and only folders which your move command cannot see.
NOTE from within a batch file, the /Y switch is disabled and folders will not be replaced if exist. So if you plan on overwriting often, perhaps rather use xcopy and update archive instead, then run a delete in d:\temp once the files have successfully copied.
Lastly, always enclose your paths in double ". In this case it will work fine without the double quotes, but if you have something like move d:\program files\temp\* d:\temp\archives it will create an error because of the space between program and files so it is always better to use move "d:\program files\temp\*" "d:\temp\archive
EDIT Understanding the %%~ assignments. In these examples we use %%I instead of %%a
%~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
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
%~dp$PATH:I : searches the directories listed in the PATH
environment variable for %I and expands to the
drive letter and path of the first one found.
%~ftzaI : expands %I to a DIR like output line`

How to create subfolders while using FOR /F in a Batch file

I want to process a folder and files in sub folders and after processing want to move files to new location (folder).
Current command is working but it is not creating sub folders and generating all new files in same folder (i.e. output folder)
for /F %%i in (filelist.txt) do (process.exe %%i > output\%%~nxi)
I need it to save it in same folder structure, as its source folder.
Where filelist.txt (source folder) is:
c:\backup\oldwork\browse.asp
c:\backup\oldwork\capital.asp
c:\backup\oldwork\make.asp
c:\backup\oldwork\conf\config.asp
c:\backup\oldwork\conf\global.asp
and I want my script to generate output (destination folder) like:
c:\backup\output\browse.asp
c:\backup\output\capital.asp
c:\backup\output\make.asp
c:\backup\output\conf\config.asp
c:\backup\output\conf\global.asp
Currently above For /F command is generating output like:
c:\backup\output\browse.asp
c:\backup\output\capital.asp
c:\backup\output\make.asp
**c:\backup\output\config.asp** (not following directory structure)
**c:\backup\output\global.asp**
The reason your code doesn't work is to do with what your outputting:
output\%%~nxi
Where if you check your documentation you would see:
You can now use the following optional syntax:
%~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
The modifiers can be combined to get compound results:
%~nxI - expands %I to a file name and extension only
Since you are only expanding to name and extension, the folder structure is ignored.
Solution:
What I would do in your situation is this, change your filelist.txt to this format:
browse.asp
capital.asp
make.asp
conf\config.asp
conf\global.asp
And then change your for-loop as such:
for /F %%i in (filelist.txt) do (process.exe c:\backup\oldwork\%%i > output\%%i)
Which should work out for you.
for /F %%i in (filelist.txt) do (md "output%%~pi"&process.exe %%i > "output%%~pnxi")
should do the task, creating output\backup\oldwork\browse.asp etc. (for lack of adequate description of required result)

Looping over directories in Windows XP command prompt

I have the following command which will loop over all the subdirectories in a specific location and output the full path:
for /d %i in ("E:\Test\*") do echo %i
Will give me:
E:\Test\One
E:\Test\Two
But how do I get both the full path, and just the directory name, so the do command might be something like:
echo %i - %j
And the output might be something like:
E:\Test\One - One
E:\Test\Two - Two
Thanks in advance!
The following command syntax can be used to return the full path or directory name only:
%~fI - expands %I to a fully qualified path name
%~nI - expands %I to a file name only
Using your example, the following command will list directories in the format that you specified:
for /d %i in ("E:\Test*") do echo %~fi - %~ni
You can use "%~ni". This is an enhanced substitution that will return the file name of a path (or, more accurately, the last part, which is the directory name in your case):
for /d %i in ("E:\Test\*") do echo %i - %~ni
See also this question: What does %~d0 mean in a Windows batch file?

What does %~d0 mean in a Windows 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".

Resources