So I am writing a little program in batch, and I am hoping it will be able to run it on other's computers. My cd is to C:\Users\%username%\Desktop\,\thing, but that is not where other people may store it. How can I locate where it is and do a cd to it? Thanks!
%cd% is available either to a batch file or at the command prompt and expands to the drive letter and path of the current directory (which can change e.g. by using the CD command)
%~dp0 is only available within a batch file and expands to the drive letter and path in which that batch file is located (which cannot change). It is obtained from %0 which is the batch file's name.
#echo off
echo %appdata%
CD %appdata%
pause
echo %CD%
pause
Dir
pause
echo "%~dp0%"
pause
CD "%~dp0%"
Dir
cls
echo this is %%cd%% %cd%
echo this is %%~dp0 %~dp0
pause
Programs and documents can be added to the registry so typing their name without their path in the Start - Run dialog box or shortcut enables Windows to find them.
This is a generic reg file. Copy the lines below to a new Text Document and save it as anyname.reg. Edit it with your programs or documents.
In paths use \\ to seperate folder names in key paths as regedit uses a single \ to seperate it's key names. All reg files start with REGEDIT4. A semicolon turns a line into a comment. The # symbol means to assign the value to the key rather than a named value.
The file doesn't have to exist. This can be used to set Word.exe to open Winword.exe.
This sample add IE.Txt (from IE5) to the registry so typing IE.Txt will open it. I think the file is called IE4.txt in IE4.
REGEDIT4
;The bolded name below is the name of the document or program, <filename>.<file extension>
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths\IE.txt]
;The # means the path to the file is assigned to the default value for the key.
;The whole path in enclosed in a quotation mark ".
#="\"C:\\Program Files\\Internet Explorer\\IE.txt\""
;Optional Parameters. The semicolon means don't process the line. Remove it if you want to put it in the registry
;Informs the shell that the program accepts URLs.
;"useURL"="1"
;Sets the path that a program will use as its' default directory. This is commented out.
;"Path"="C:\\Program Files\\Microsoft Office\\Office\\"
reg command can read or write to the registry in batch. Register it as if it's an exe file not a batch file.
Related
Here is an example for one file:
C:\folder\video\my-holiday-video.mp4
C:\folder\image\my-holiday-screen.png
C:\folder\mix\my-holiday-HDphoto.jpg
C:\folder\cover\my-holiday-art.jpg
What I try to do is to make a ZIP archive of files which are in different folders, but have the same name, i.e. my-holiday for the example above, but a different suffix as -video or -screen or -HDphoto or -art and keep the same folder tree in each ZIP file.
The result should be my-holiday.zip which contains all the files in their folders.
I have success with this code on all the files have the same name:
#for %%I in ("%~dp0wheel\*") do #"%ProgramFiles%\7-Zip\7z.exe" a -bd -bso0 -mx0 -r -x!*.zip -y "%~dp0%%~nI.zip" "%~dp0%%~nI.*"
But it zips only when files have all the strict same file name.
Is there a way to make my batch ignore the suffixes -video, -screen, -HDphoto and -art in the name of each file in order to make them zip together?
Here are the requirements:
The suffixes -video, -screen, -HDphoto and -art are always the same for all my files. So these are fixed in the file names.
There should be in the file my-holiday.zip:
video\my-holiday-video.mp4
image\my-holiday-screen.png
mix\my-holiday-HDphoto.jpg
cover\my-holiday-art.jpg
Each file is with its relative path in the ZIP archive. So when I decompress them, they'll be extracted in their directories, for example my-holiday-video.mp4 will decompress into folder video, my-holiday-HDphoto.jpg into folder mix, etc. like my actual code do it.
The rule for common part of a files collection is that everything left to -video before file extension .mp4 should be used as common part of the file names to pack into the ZIP file.
The folder video is the source for packing the files with common name into a ZIP file.
The task could be done with following batch file:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
cd /D "C:\folder" || exit /B
for %%I in ("video\*-video.*") do (
set "VideoFileName=%%~nxI"
setlocal EnableDelayedExpansion
set "CommonName=!VideoFileName:-video%%~xI=!"
"%ProgramFiles%\7-Zip\7z.exe" a -bd -bso0 -mx0 -y -- "!CommonName!.zip" "cover\!CommonName!-art.*" "image\!CommonName!-screen.*" "mix\!CommonName!-HDphoto.*" "video\!VideoFileName!"
endlocal
)
endlocal
The batch file defines with the first two command lines the required execution environment which is:
command echo mode turned off
command extensions enabled
delayed expansion disabled
The next command changes the current directory to C:\folder. If that command fails because of the directory does not exist or a UNC path is used instead of a path starting with a drive letter and a colon, the batch file processing is exited without any further message than the error message output by command CD.
The FOR loop searches in subdirectory video for non-hidden files matching the wildcard pattern *-video.*. The file name with file extension of a found video file matching this wildcard pattern is assigned to the environment variable VideoFileName.
Next delayed expansion is enabled as required to make use of the file name assigned to the environment variable VideoFileName. Please read this answer for details on what happens in background on execution of setlocal EnableDelayedExpansion and later on execution of corresponding endlocal.
A case-insensitive string substitution using delayed expansion is used to remove from video file name -video left to the file extension and the file extension itself which can be .mp4, .mpg, .mpeg, etc. VideoFileName was defined with file extension in case of the file name itself contains anywhere the string -video which should not be removed by the string substitution. For example My Home-Video-video.mp4 assigned to VideoFileName results in My Home-Video getting assigned to the environment variable CommonName because of taking also the file extension into account on string substitution.
Next 7-Zip is executed with the command a and the switches as posted in question to create or add to a ZIP file in current directory with common name part of the files in the four directories and file extension .zip the video file name and the other image files from the other three directories with whatever file extension the images have in the other three directories.
Then endlocal is executed to restore the previous environment with delayed expansion disabled again.
The commands setlocal EnableDelayedExpansion and endlocal are used inside the FOR loop to be able to process correct also a files collection with a common name like Superman & Batman (+ Robin!) containing an exclamation mark.
The video files in subdirectory video define which files to pack into a ZIP file. So all image files in the three image directories are ignored for which no video file exists in directory video.
Note: The batch file is not capable processing correct video file names which contain an exclamation mark in the file extension. I doubt that this limitation is ever a problem as I have never seen a video file extension with an exclamation mark.
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.
cd /?
echo /?
endlocal /?
exit /?
set /?
setlocal /?
See also single line with multiple commands using Windows batch file for an explanation of conditional operator ||.
I have this cmd command (that I found here) that makes me list all image files in the current folder:
for %i in (*) do echo ^<img src="%i" /^> >> all.html
So if I want to run this I need to go to cmd and manually input the folder path every time I run said code.
Can I put this in a batch file/cmd file so I can just put the batch file/cmd file in any folder I want and it will run the code?
I believe you are looking for %~DP0 which is only available within a batch file and displays the current drive and directory in which that batch file is located note, this cannot change. It is obtained from %0 which is the batch file's name.
%CD% on the other hand is available either to a batch file or at the command prompt and expands to the drive letter and path of the current directory. Which could change by using CD for instance.
More info
Full answer is given by Compo:
#(for %%i in ("%~dp0*") do #echo ^<img src="%%i" /^>)>"all.html"
I use the following command to export data from a source file to target file in CSV format.
C:\MyApp.EXE -export "C:\Test\Sample.dat" "C:\Test\results.CSV"
However I need to repeat the same command multiple times just by changing the source and target files. something like this
C:\MyApp.EXE -export "C:\Test\Sample01.dat" "C:\Test\results01.CSV"
C:\MyApp.EXE -export "C:\Test\Sample02.dat" "C:\Test\results02.CSV"
C:\MyApp.EXE -export "C:\Test\Sample03.dat" "C:\Test\results03.CSV"
I'm looking to create a batch file to do the job. I have tried the following in a batch file and ran, but it is opening multiple console windows all at the same time. I want all this to happen in just one Command window and run the commands one after the other.
cd "C:\Test\"
start MyApp.EXE -export "C:\Test\Sample.dat" "C:\Test\results.CSV"
start MyApp.EXE -export "C:\Test\Sample01.dat" "C:\Test\results01.CSV"
I want code to create a batch file which runs MyApp.exe multiple times with arguments.
I'm using PowerShell to generate the batch file, so I don't need variables in the .bat file.
This task could be done with following batch file:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
for %%I in ("C:\Test\Sample*.dat") do (
set "FileNameCSV=%%~nI"
set "FileNameCSV=!FileNameCSV:Sample=results!"
C:\MyApp.exe -export "%%I" "%%~dpI!FileNameCSV!.csv"
)
endlocal
Command FOR searches in specified directory C:\Test for all files matching the wildcard pattern Sample*.dat. For each file the fully qualified file name (drive + path + name + extension) is assigned to loop variable I.
The first command in body command block of FOR loop assigns just the file name to environment variable FileNameCSV. On this line a DAT file name with one or more exclamation marks would not be interpreted as most users expect. The exclamation mark(s) would be interpreted as beginning/end of a delayed expanded environment variable reference. However, this is no problem here according to file names in question.
The second SET command line uses a simple case-insensitive string substitution to replace all occurrences of sample by results in CSV file name.
The environment variable must be referenced with delayed expansion using !VariableName! syntax. Otherwise the Windows command line interpreter cmd.exe would expand (= replace) the reference of the environment variable on using %VariableName% on parsing entire command block starting with ( and ending with matching ) before FOR is executed at all.
The third command line executes your application with the input file name with full path and extension and the CSV file name also with full path of input file, but with modified file name and a different file extension.
But faster would be following batch code also working for files with ! in fully qualified file name.
#echo off
for %%I in ("C:\Test\Sample*.dat") do C:\MyApp.exe -export "%%I" "%%~dpI_%%~nI.csv"
ren "C:\Test\_Sample*.csv" "results*.csv"
The FOR loop executes your application with each *.dat as input file and with _*.csv as output file, i.e. _Sample.csv, _Sample01.csv, ...
The CSV files are renamed after finishing processing all DAT files to results.csv, results1.csv, ...
Adding the additional underscore is necessary to rename all _Sample*.csv correct to results*.csv. The number of characters before wildcard character * must be the same in current and new file name.
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.
echo /?
endlocal /?
for /?
ren /?
set /?
setlocal /?
But I do not really understand why all this is done with a batch file executed by Windows command line interpreter cmd.exe if this batch file is really created with a PowerShell script executed by script interpreter powershell.exe. All this can be done also from within the PowerShell script by using the appropriate PowerShell script functions.
I'm trying to run a .bat file globally by adding the directory which contains it to PATH. This obviously works for exe files but is there a way to run .bat files this way?
As #SLaks said in his comment, this will work.
Based on the rest of your comments, you need to specify the full file name. If there's program.exe and program.bat, you need to enter program.bat and not just program at the command prompt.
When you enter program at a command prompt, the shell will first try to execute program.com, then program.exe, then program.bat. The exact order is saved in the PATHEXT environment variable:
C:\Windows>echo %PATHEXT%
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
Original MS-DOS didn't have this variable, as I recall. It searched .COM, .EXE, and then .BAT so the behavior has preserved since MS-DOS 3.3 (and I believe since IBM DOS 1.0), but I believe it was hard-coded. The PATHEXT variable was introduced with Windows NT, IIRC.
Edit to add:
Ah, alright. It sounds like your batch file also needs to change to it's own directory so that the current working directory is wherever it's at. The easy way to do that is at the beginning of the batch file (after your #echo off) put:
pushd %~dp0
This will change the current working directory to wherever the batch file is. And then at the very last line:
popd
That will change the current working directory to what ever the current working directory was before the last time that pushd was run.
The two commands, pushd and popd, are like advanced change directory commands. If you're at C:\ and you type pushd C:\Program Files\, you'll change to that directory. Then if you type popd, you'll go back where you just were at C:. You can do it multiple times, each time "pushing" another directory onto the "stack" of your directory history. popd then removes the top of the stack, and takes you back one. Think of it like the back button on your browser. You can even change the drive at the same time. pushd D:\ will change to the D: drive and set the directory to the root of D:.
Now, the %~dp0 is a bit weirder. It's a modified variable.
You might know that the arguments for a batch file get assigned to special variables. %1 is the first argument, then %2 is the second, %3 the third, and so forth up to %9. %0 is the zeroth argument. That's the name of the actual batch file itself. If we run program.bat from the C:\Folder\ directory, %0 is probably program.bat.
The tidle (~) removes double quotes around the argument. So %~0 is the file name of the batch file without any quotation marks, which can appear if you have spaces in your file or folder names.
The d means "drive letter only". So %~d0 would be C: (assuming we're on the C: drive).
The p means "path only". So %~p0 would be \Folder\.
We want both, so dp means "drive and path only". So %~dp0 expands to C:\Folder\.
So, the first line of the batch file is now:
pushd C:\Folder\
But it's dynamic! So if you move it to D:\AnotherFolder\, it will still work without needing to edit it. You can find a full list of the variable modifications that cmd.exe understands under the for command.
You can also add .bat files to PATH though the control panel:
Hit the windows key ⊞ Win, and start typing environment.
Click enter on the control panel option:
Click on environment variables:
Scroll down to Path, and click edit:
Then click new, and enter the folder of the batch file.
If your file is named abc.bat, and it is in your PATH, you can run it from CMD with:
abc
Here's a simple example with two bat files, caller.bat and callee.bat in the same directory.
caller.bat
call callee.bat
pause
callee.bat
echo "All good"
When I run caller.bat by double clicking it in Explorer it works as expected but if use right-click "Run as administrator" I get
'callee.bat' is not recognized as an internal or external command...
The problem is that when run as administrator the current working directory is changed to C:\Windows\System32. My solution was to explicitly change the current working directory in caller.bat to be the same as the directory from where the file is run. This is done by extracting the drive and path from the %0 parameter as shown below:
cd /D %~dp0
call callee.bat
pause
The /D argument to cd causes the directory as well as the path to change and is needed to handle the case where the caller .bat file is not on the C: drive.
More info here: Hidden features of Windows batch files
Another solution is to add the directory where your scripts are stored to your path system environment variable. You could do this through the GUI that windows provides in the advanced system settings (type environment variable into the start menu and you should see the option), or you can run a cmd session as admin and enter:
setx path %path%;"your script dir" /M
The /M makes it system wide, not just your user (this is what requires the admin). The double quotes are only required if your path has any spaces in it. The path variable contains a list of paths delimited by semi-colons. The above just appends a new entry to the existing list. Adding an entry to the list allows you to execute programs from this directory without specifying the path.
Finally, if this does not work on it's own you may need to also add .cmd and/or .bat to your pathext variable:
setx pathext %pathext%;.cmd;.bat /M
To check the current values of the variables do set var_name i.e.:
set pathext