batch: change current directory and print it in one line - batch-file

how to change the current directory and print it in one line?
I tried C:\dir1> cd /d D:\dir2 && echo %cd%
but it prints C:\dir1

You should be able to do cd /d D:\dir2 && cd
According to the windows cmd help page for cd/chdir this will display your current directory:
Type CD drive: to display the current directory in the specified
drive.
Type CD without parameters to display the current drive and
directory.

Related

Batch file to read the root directory it is in

Is there a batch command that can read a root directory without the entire path?
I want a batch file to tell me if its in D:\ or E:\.
I tried to use:
set mypath=%cd%
#echo %mypath%
Pause
But it just says the exact place it is in rather than just the root.
Here's a few options for you which provide the root directory of the scripts current directory:
Using PushD/Popd
PushD\&Call Set "RootDir=%%CD%%"&PopD
Echo(%RootDir%
Pause
Using a For loop
For %%A In (%CD%) Do Set "RootDir=%%~dA\"
Echo(%RootDir%
Pause
Using variable expansion
Set "RootDir=%CD:~,3%"
Echo(%RootDir%
Pause
Edit
After reading your question again, I decided to add a fourth example. This one unlike the other three provides the root directory of the batch files location.
Set "RootDir=%~d0\"
Echo(%RootDir%
Pause
the directory where the batch file is located could be different from the current directory cmd.exe operates in.
TO get the batch file root path use:
for %%a in ("%0") do echo %%~da
To ger the current directory use
echo "%cd:~0,3%"
And let us not forget the &REM trick.
#ECHO OFF
set "root=%cd:\="&rem %
echo %root%

Why is a folder not deleted with RMDIR in batch file as last command?

I have the following code in a .bat file:
#echo off
xcopy /Y /S %CD%\Code\Release C:\Users\%USERNAME%\Desktop\ShareIt /I
cls
cd C:\Users\%USERNAME%\Desktop\ShareIt\
call "Trabalho AEDA.exe"
xcopy /Y /S C:\Users\%USERNAME%\Desktop\ShareIt\FICHEIROS\ %CD%\Code\Release\FICHEIROS\
RMDIR /S /Q C:\Users\%USERNAME%\Desktop\ShareIt
That copies a folder to a location, runs the .exe from it and then it overwrites the original files in my folder and has do delete the ones initially copied.
The folder I copy to the user desktop has other folder inside, and the .exe.
At the final line of the .bat, it deletes everything in the folder, but the folder is kept in the Desktop folder. I want to delete it, too. I tried several instructions, but without success.
EDIT: That was the issue, thanks guys.
ShareIt folder isn't deleted probably because you are in the folder.
So, adding cd .. before RMDIR /S /Q C:\Users\%USERNAME%\Desktop\ShareIt solves it.
The main problem with deleting ShareIt folder is already answered by the other answers.
It is not possible on Windows to delete a folder which is the current working directory of any running process or in which a file is opened by an application with a file lock preventing the deletion of the opened file.
In this case the ShareIt folder is the current working directory of the command process executing the batch file because the batch file explicitly sets this directory as working directory. The solution is making any other directory the working directory for the command process.
But this is not the only potential problem of the few command lines of this batch file. There are some more.
%CD% could expand to a path which contains perhaps one or more spaces or other characters like &()[]{}^=;!'+,`~ which require enclosing complete folder path in double quotes. This list of characters is output on running in a command prompt window cmd /? in last paragraph on last output help page.
Also %CD% expands to a folder path usually not ending with a backslash, except the current directory is the root directory of a drive. So %CD%\Code\Release could for example expand to C:\\Code\Release with two backslashes in path. However, this is no real problem as Windows kernel corrects the path automatically on whatever file system access function is used internally by xcopy for copying the files and folders.
Parameter /I lets xcopy interpret the target string as folder path even if folder path is not ending with a backslash, but only if multiple files are copied like when source path is a folder path like it is here obviously the case. Otherwise on copying just a single file /I is ignored by xcopy. Best for a folder path as target is specifying the target folder path with a backslash as then xcopy interprets target always as folder path. It is easier to use here paths relative to current directory and omit %CD% completely.
C:\Users\%USERNAME% is not good as the user's profile directory can be also on a different drive than C: and can be in a different directory than Users, for example on Windows XP. The path C:\Users\%USERNAME% is the default for the user's profile directory since Windows Vista. But every user has the freedom to change it also on Windows Vista and later Windows versions. There is the environment variable USERPROFILE defined by Windows which contains full path to active user's profile directory. See Wikipedia article about Windows Environment Variables for more details about predefined Windows environment variables.
And of course the user's profile directory path could contain one or more spaces or other characters which again require double quotes around complete folder path or file name, for example if the user account name contains a space character. So again double quotes should be used wherever %USERPROFILE% or %USERNAME% is used in a folder or file name with path.
Command CD without parameter /D changes the current directory only on current drive if the new current directory exists at all on current drive. So with current directory on starting the batch file being on a different drive than drive C:, changing the current directory with used code would not work at all.
The command CALL should not be necessary at all in case of Trabalho AEDA.exe is really an executable as the file extension indicates. CALL can be used also for an executable, but it is designed primary for running a subroutine or calling another batch file from within a batch file.
The last two lines do not really make sense because the current directory was changed by the batch file to ShareIt folder in desktop folder of current user. Therefore %CD%\Code\Release\FICHEIROS\ expands to
C:\Users\%USERNAME%\Desktop\ShareIt\Code\Release\FICHEIROS\
as target path for xcopy and the last line deletes the entire folder
C:\Users\%USERNAME%\Desktop\ShareIt
That is obviously not the intention. xcopy in last but one line should copy the files to a subdirectory in initial current directory.
I suggest to use this batch code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
%SystemRoot%\System32\xcopy.exe Code\Release "%USERPROFILE%\Desktop\ShareIt\" /C /Q /R /S /Y >nul
pushd "%USERPROFILE%\Desktop\ShareIt"
if not errorlevel 1 "Trabalho AEDA.exe" & popd
%SystemRoot%\System32\xcopy.exe "%USERPROFILE%\Desktop\ShareIt\FICHEIROS" Code\Release\FICHEIROS\ /C /Q /R /S /Y >nul
setlocal EnableDelayedExpansion
if "!CD:%USERPROFILE%\Desktop\ShareIt=!" == "!CD!" RMDIR /S /Q "!USERPROFILE!\Desktop\ShareIt"
endlocal
endlocal
The last IF conditions needs most likely an additional explanation for what is its purpose.
!CD:%USERPROFILE%\Desktop\ShareIt=! results in searching case-insensitive in current directory path string for all occurrences of the path string to ShareIt directory in desktop directory of current user and replacing all found occurrences by an empty string. So it depends on what is the current directory on what happens here.
In case of current directory is %USERPROFILE%\Desktop\ShareIt, the string left of comparison operator == becomes "". In case of current directory is a subdirectory of %USERPROFILE%\Desktop\ShareIt, the string left of == becomes a relative path to this directory enclosed in double quotes. In all other cases the string left of == is not modified at all and expands to path of current directory enclosed in double quotes like the string right of the comparison operator.
So the IF condition checks if the current directory is NOT the ShareIt directory or a subdirectory of this directory in the desktop directory of current user. Only in this case it is safe to delete the entire ShareIt directory.
Note: The IF condition does not work correct on %USERPRFOLE% expands to a folder path string containing one or more ! because of enabled delayed variable expansion.
For understanding all other 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 /?
cd /?
echo /?
endlocal /?
if /?
popd /?
pushd /?
set /?
setlocal /?
xcopy /?
There should be read also the Microsoft documentation about Using command redirection operators for an explanation of >nul.
Since you execute
cd C:\Users\%USERNAME%\Desktop\ShareIt\
It's the current directory when you execute the now delete the directory command.
Move to another directory, and then try the deletion

I need to traverse all subdirectories with batch script including changing working directory?

There's a program that processes a file and outputs in the working directory.
So this doesn't work:
for /r "d:\root folder\" %%i IN (*.xma) do d:\whatever-path\program.exe "%%i"
I puts the output in the root folder instead of where the input is.
Any ideas?
If program.exe output its data in the current active directory and the output must be in the same folder that the input data, you can use
for /r "d:\root folder" %%i in (*.xma) do (
pushd "%%~dpi"
d:\whatever-path\program.exe "%%i"
popd
)
changing the current active directory to the one where the file is stored and, after running your command, restoring the previous active directory

When is the CD environment variable updated?

The tipp to use the CD environment variable from batch scripts to get the current working directory is commonly posted. But CD won't get updated when calling another batch file. Then the cd command echoes the new path of the other batch file, but %CD% (or !CD!) is not updated. Example:
#echo off
cd %~dp0
echo in %0: CD=%CD%
pause
call X:\testcall.cmd
Save this as C:\testcall.cmd and X:\testcall.cmd, then run C:\testcall.cmd. You should see that the value of CD has not changed. This seems not to dependend on call; none of the following works:
start /D <NEW_DIR> <OTHER_CMD_FILE>
start cmd /c <NEW_DIR>\<OTHER_CMD_FILE>
cmd /c <NEW_DIR>\<OTHER_CMD_FILE>
<NEW_DIR>\<OTHER_CMD_FILE>
cd %~dp0
pushd %~dp0
CD will keep it's old value, while cd (the command) shows the correct directory. Therefore I set CD at the begin of a script:
set CD=%~dp0
...while assuming cmd.exe sets CD only if this variable is yet unset. True?
%CD% is the current directory, while %~dp0 is the directory of the currently-running script (with trailing '\').
Also, don't set an env. var called CD, since it will override the default %CD% pseudo-var, and will be incredibly confusing - see OldNewThing - ERRORLEVEL is not %ERRORLEVEL%.
For example, when running c:\temp\a.cmd, which is:
#echo off
echo Currently running script: %~dpnx0
cd %~dp0
echo scriptDir=%~dp0, CD=%CD%
cd %~dp0a
echo scriptDir=%~dp0, CD=%CD%
set CD=bogus value
echo scriptDir=%~dp0, CD=%CD%
output:
Currently running script: c:\temp\a.cmd
scriptDir=c:\temp\, CD=c:\temp
scriptDir=c:\temp\, CD=c:\temp\a
scriptDir=c:\temp\, CD=bogus value
Diagnosis
You have at some point set the CD variable explicitly. If you do this it will no longer automatically reflect the current working directory. To undo this, set it to empty:
set CD=
It will then begin working again.
Why is this? Well, the automatic CD variable was introduced as a feature. I assume they just didn't want to break pre-existing scripts which already used that varible name. So if you set it explicitly, CMD will assume you are doing so on purpose.
Discussion
Firstly, if the parent process has an explicitly set CD variable, it will be inherited by the child processes.
On the other hand, you shouldn't expect any of these to update the value of %CD% for the parent process:
start /D <NEW_DIR> <OTHER_CMD_FILE>
start cmd /c <NEW_DIR>\<OTHER_CMD_FILE>
cmd /c <NEW_DIR>\<OTHER_CMD_FILE>
These all create new processes, the new process then changes its own working directory. You should not expect this to affect the parent process.
The final one, does not update the working directory at all, unless OTHER_CMD_FILE executes a CD command:
<NEW_DIR>\<OTHER_CMD_FILE>
Just because you executed a script in a different directory does not mean that the script's working directory will change. The script working directory does not have to be set to the location of the script.
Advice
Relying on the working directory being set to anything in particular is generally a bad idea.
You probably want something like this:
SET SCRIPT_DIR=%~dp0
Then use (for example) "%SCRIPT_DIR%\config.txt" to refer to a file in that directory.
Alternatively if you wish to rely on the current directory, use cd /d %~dp0
I build two batch files from your comment
test1.bat - located in C:\temp
#echo off
cd %~dp0
echo File %~f CD=%CD%
call X:\test2.bat
test2.bat - located in *X:*
#echo off
cd %~dp0
echo File %~f CD=%CD%
Starting test1 it from C:\temp, the output is
File C:\temp\test1.bat CD=C:\temp
File X:\test2.bat CD=C:\temp
The result is absolutly correct!
Starting a batch file (or any other program) with an absolute or relative path doesn't change the current directory.
The CD seems to fail, as CD can't change the drive the way you used it.
You need to add a switch CD /d %~dp0
You can set the %cd% variable to whatever you want, the real current directory for the C: drive is stored in the %=c:% variable, and you can't change this with the set command:
#echo off
echo Currently running script: %~dpnx0
cd %~dp0
echo scriptDir=%~dp0, CD=%CD%
set CD=bogus value
echo scriptDir=%~dp0, CD=%CD%, =c:=%=c:%
set =c:=bogus value
echo scriptDir=%~dp0, CD=%CD%, =c:=%=c:%
Output is:
Currently running script: C:\OldDir\a.bat
scriptDir=C:\OldDir\, CD=bogus value
scriptDir=C:\OldDir\, CD=bogus value, =c:=C:\OldDir
syntax error.
scriptDir=C:\OldDir\, CD=bogus value, =c:=C:\OldDir
The =C: variable for a child process is always set from the parent process. If you avoid the setlocal command in your script OR choose endlocal, you can change persistend the current directory for the current cmd session:
C:\OldDir>type script.bat
cd c:\newdir
C:\OldDir>script
C:\OldDir>cd c:\newdir
C:\NewDir>
.
C:\OldDir>type script.bat
setlocal
cd c:\newdir
C:\OldDir>script
C:\OldDir>setlocal
C:\OldDir>cd c:\newdir
C:\OldDir>
Using the script-directory %~dp0 can be a solution, but usually isn't. This works better:
cd >tmpfile
set /P CD= <tmpfile
del tmpfile
This solution is consistent with the CD variable. CD contains the current directory, not ending in a slash character if it is not in the root directory of the current drive. The path printed by cd behaves exactly so.
I'm using this for years and had no problems setting CD explicitly. Later I began using PWD (as in Bash). This variable is not reserved in MSDOS. So my question here was actually: "Can we get rid of these lines, or is this some MSDOS idiom?"
Some have written that setting CD explicitly is bad. Why? MSODS was never properly designed, and is not further developed. Anything you can do with it is legal. There is no bad MSDOS programming - just good and bad hacks. I know no other language where this perspective is legal to such an extent.

Batch File - going back two steps in a directory path

I am creating a batch file i am on a path
C:\Validation\docs\chm
I want to move back to the
C:\Validation part
which is in %DialogPath%
This was entered by the user but when i write
CD /D %DialogPath%
An error occurs that tells this path does not exists
The direct answer to your question would be
cd ..\..
But cd /D C:\Validation also works.
The problem is more likely with the variable than then command.
Until you give more details as to the script in question, we can only guess to what the problem may be.
However, since you are changing the current directory only for a limited time you should be using the pushd and popd commands.
Example: (Run this .bat script to see how pushd and popd work!)
:: Hide Commands
#echo off
:: Display Current Working Directory
echo Current Directory = %CD%
:: Create folders for demonstration purposes only
rd /Q "%Temp%\Test" 2>nul & mkdir "%Temp%\Test" & mkdir "%Temp%\Test\Subfolder"
:: Change the Working Directory
pushd "%Temp%"
:: Display Current Working Directory
echo Current Directory = %CD%
pushd "%Temp%\Test\Subfolder"
:: Display Current Working Directory
echo Current Directory = %CD%
:: Revert back to the previous Working Directory
popd
:: Display Current Working Directory
echo Current Directory = %CD%
:: Revert back to the previous Working Directory
popd
:: Display Current Working Directory
echo Current Directory = %CD%
pause
For help type pushd /? or popd /? into the command prompt.
You can move up one path with cd ... If you do that twice, you will land in the C:\Validation directory.
In your example it would look like this:
C:\Validation\docs\chm> cd ..
C:\Validation\docs> cd ..
C:\Validation>

Resources