How can I copy and rename a file using an environment variable? - batch-file

I'm working with the command prompt for nearly the first time and am required to create a batch file that prompts the user for a filename with an extension. The bat is supposed to be able to copy and rename said file. The instructor has directed us to use environmental variables to accomplish this task, but I keep getting directory or syntax errors.
I've tried using the variable that the user sets with a previous prompt, but unfortunately this particular instructor hasn't given us practical examples about how to accomplish this particular goal, so I'm flailing. I've tried attaching the variable to the target directory with a generic name for the file. The file and the copy should be in the dame directory.
set /P file_var=Please enter a file name and extension:
copy %file_var% Templatecopy.doc
The file should be copied with the new default name of "Templatecopy.doc" in the target directory.
Churns out syntax and directory errors.

I suggest the following commented code to make this batch file fail-safe as described in answer on How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?
#echo off
:FileNamePrompt
rem Undefine environment variable FileToCopy.
set "FileToCopy="
rem Prompt user for the file name.
set /P "FileToCopy=Please enter a file name and extension: "
rem Has the user not entered anything, prompt the user once more.
if not defined FileToCopy goto FileNamePrompt
rem Remove all double quotes from user input string.
set "FileToCopy=%FileToCopy:"=%"
rem Has the user input just one or more ", prompt the user once more.
if not defined FileToCopy goto FileNamePrompt
rem Check if the user input string really references an existing file.
if not exist "%FileToCopy%" (
echo File "%FileToCopy%" does not exist.
goto FileNamePrompt
)
rem Check if the user input string really references
rem an existing file and not an existing directory.
if exist "%FileToCopy%\" (
echo "%FileToCopy%" references a directory.
goto FileNamePrompt
)
copy /B /Y "%FileToCopy%" "%~dp0Templatecopy.doc" >nul
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 %~dp0 which is expanding to drive and path of argument 0 which is the batch file path always ending with a backslash.
copy /?
echo /?
goto /?
if /?
rem /?
set /?

Related

Test IF file exist, del this local file

This question is related to Test IF file exist, ELSE xcopy these two files.
Background: On occasion I choose to run aGallery-dl.bat in a given folder (just one in each of 100's of folders). It first deletes Folder.jpg then renames Folder2.jpg to Folder.jpg. This has the effect of a red X being replaced by a yellow ! when viewing the folder with parent folder selected in File Explorer. Secondly, it calls gallery-dl.exe. I use going from red X to yellow ! to let me know I've run aGallery-dl.bat at least once. If aGallery-dl.bat completes successfully, it finally deletes the Folder.jpg (currently yellow !), and now the representative contents of the folder (usually DeviantArt .jpg's) are visible. All is well.
rem #echo off
del .\Folder.jpg
ren .\Folder2.jpg Folder.jpg
FOR /F %%i IN ('cd') DO set FOLDER=%%~nxi
"C:\Program Files (x86)\gallery-dl\gallery-dl.exe" -d "U:\11Web\gallery-dl" --download-archive ".\aGDB.sqlite3" "https://www.deviantart.com/"%FOLDER%"/gallery/all"
del .\Folder.jpg
Problem: Restating, Gallery-dl.bat is in each of 100's of folders. On occasion, I run one of these from within it's local folder. Line 5, if the call to the web site is successful, gallery-dl.exe creates zzzGDB.sqlite3 within the local folder.
In the previous code, when aGallery-dl.bat completed, it would just delete the Folder.jpg. This assumes the call to the web page was successful. On rare occasion, the call to the web page will fail for any number of reasons, though at close (due to that final del .\Folder.jpg), it will still delete folder.jpg.
If zzzGDB.sqlite3 was not created/not present, I need the Folder.jpg (yellow !) to remain.
So, in the below code (line 6, now blank), I've lopped off the final del .\Folder.jpg and am trying to plug-in the provided code beginning at line 7, inserting a test for zzzGDB.sqlite. If found, del .\Folder.jpg. If not found, no action is taken against folder.jpg (it remains).
(The rem statement at the very bottom is just acting as a placeholder for my own knowledge.)
rem #echo off
del .\Folder.jpg
ren .\Folder2.jpg Folder.jpg
FOR /F %%i IN ('cd') DO set FOLDER=%%~nxi
"C:\Program Files (x86)\gallery-dl\gallery-dl.exe" -d "U:\11Web\gallery-dl" --download-archive ".\zzzGDB.sqlite3" "https://www.deviantart.com/"%FOLDER%"/gallery/all"
setlocal EnableExtensions DisableDelayedExpansion
for /D %%I in ("U:\11Web\gallery-dl\deviantart\*") do (
if exist "%%I\zzzGDB.sqlite3" (
del "%%I\Folder.jpg"
)
rem
)
endlocal
Note: Currently, the modified code goes back through every single folder within U:\11Web\gallery-dl\deviantart\*. This action should be reserved only to the local folder. I'm guessing the below is the issue.
for /D %%I in ("U:\11Web\gallery-dl\deviantart\*")
I don't know how to remove it and still implement everything after do?
do (
if exist ".\zzzGDB.sqlite3" (
del ".\Folder.jpg"
)
rem
)
I suggest to use following lines for aGallery-dl.bat.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0" || exit /B
move /Y "Folder2.jpg" "Folder.jpg"
for %%I in (.) do set "FOLDER=%%~nxI"
"%ProgramFiles(x86)%\gallery-dl\gallery-dl.exe" -d "U:\11Web\gallery-dl" --download-archive "%~dp0zzzGDB.sqlite3" "https://www.deviantart.com/%FOLDER%/gallery/all"
if not errorlevel 1 if exist "zzzGDB.sqlite3" del "Folder.jpg"
popd
endlocal
The first two lines define the execution environment for the batch file.
The third line with command PUSHD pushes the current directory path on stack and sets the directory of the executed batch file as current directory. This works even on batch file being stored on a network resource accessed using a UNC path, except there is a network problem on execution of that command line.
The command exit /B is executed in case of an error to immediately exit processing of the batch file on batch file directory could not be set as current directory. The Windows command processor runs implicitly the command ENDLOCAL in this case.
See Single line with multiple commands using Windows batch file for an explanation of operator || which results in conditionally executing exit /B only if pushd exited with a non-zero exit code indicating an error.
The fourth command line with MOVE does not really move the data of file Folder2.jpg to file with name Folder.jpg. In real it just updates the file system in this case as done also by the two commands del .\Folder.jpg and ren .\Folder2.jpg Folder.jpg in your batch file. This is just a very little bit faster method to replace one file by another file with the advantage that Folder.jpg must not exist at all for success without displaying an error message as done by command DEL on file Folder.jpg not existing.
The FOR command line determines the name of the current folder without path and assigns it to environment variable FOLDER. This is a much faster and safer solution then using the command line:
FOR /F %%i IN ('cd') DO set FOLDER=%%~nxi
The command line above results in starting in background one more command process with %ComSpec% /c and the command line between ' appended as additional arguments. So there is executed in background with Windows installed to C:\Windows:
C:\Windows\System32\cmd.exe /c cd
The started cmd.exe executes internal command cd which outputs the full qualified folder name of current directory to handle STDOUT of background command process. This output is captured by cmd.exe processing the batch file and is processed by for after started cmd.exe closed itself after finishing execution of command CD.
The command FOR would split up the folder path into substrings (tokens) using normal space and horizontal tab as string delimiters, would look next if the first space/tab delimited string starts with a semicolon in which case the captured line would be ignored for further processing, and would assign otherwise just the first space/tab delimited string to loop variable i. So if the full qualified folder name of current directory would contain a space, this command line would fail to determine the folder name of current directory without path.
There is the dynamic variable CD of which value can be referenced with %CD%. The value is the full qualified folder name of current directory not ending with a backslash, except the root directory of a drive is the current directory. That would be identical to %~dp0 for batch file aGallery-dl.bat with the difference that %~dp0 expands to full qualified name of batch file folder always with a backslash at end.
However, neither dynamic variable CD nor %~dp0 nor execution of command CD in a separate command process in background are really useful to get name of current directory (= batch file directory) without path. The best method is using:
for %%I in (.) do set "FOLDER=%%~nxI"
This simple FOR does nothing else than getting name of current folder without path with a very fast executed file system query and assigning it to environment variable FOLDER.
Note: for %%I in ("%~dp0.") do set "FOLDER=%%~nxI" could be also used to get folder name without path of folder containing currently executed batch file if the current directory would not be the batch file directory.
The sixth command line executes gallery-dl.exe with various parameters (arguments).
Please note that "https://www.deviantart.com/"%FOLDER%"/gallery/all" is in real an invalid argument string. It is not valid to have " inside a URL. The character " is never valid inside an argument string which references a file or folder. This syntax error is detected and automatically fixed which is the reason why the command line in your batch file works at all. The correct argument string is "https://www.deviantart.com/%FOLDER%/gallery/all" with one " at beginning and one " at end and no double quote inside the argument string enclosed in double quotes.
There is standard for console applications to exit with value 0 on success and a greater value like 1 on an error. I don't know if this is true also for gallery-dl.exe, but I assume that with the command line:
if not errorlevel 1 if exist "zzzGDB.sqlite3" del "Folder.jpg"
if not errorlevel 1 checks if exit code of gallery-dl.exe assigned to dynamic variable errorlevel is NOT greater or equal 1 which means less than 1 which means equal 0 (on executable never exiting with a negative value which is not recommended to do by a program on any operating system) which means no error occurred during execution of gallery-dl.exe. Please read the documentation of gallery-dl.exe regarding to exit codes of this program or find it out with several executions in a command prompt window and using echo Exit code is: %errorlevel% after each execution of gallery-dl.exe with success or an error (like a wrong URL).
That condition should be already enough. But there is used one more condition to check for existence of the file zzzGDB.sqlite3 in current directory only before deleting the file Folder.jpg in the current directory which is the batch file directory.
Please read issue 2 in this answer for the reason writing in batch file
if not errorlevel 1 if exist "zzzGDB.sqlite3" del "Folder.jpg"
instead of
if not errorlevel 1 (
if exist "zzzGDB.sqlite3" (
del "Folder.jpg"
)
)
The code above works also, but requires more CPU cycles for being processed by Windows command processor than the single line with two IF commands and one DEL command on one command line.
The last but one line pops the full qualified folder name of initial current directory from stack and sets it again as current directory and the last line restores initial execution environment on starting the batch file.
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 %~dp0 ... drive and path of argument 0 ... full batch file path.
del /?
echo /?
endlocal /?
exit /?
for /?
move /?
popd /?
pushd /?
set /?
setlocal /?

having trouble using spaces in folder names

When the user enters a space in the folder name, I can create and remove the folder with the following code, but the line to start or open the folder will not work.
I have tried several different things. If I use the "%input%" in the start line the quotes are used as part of the folder name so it is not recognized. If I eliminate the ""'s only the first word in the name is recognized so the folder is not found. the Md and Rd lines work perfectly with the quotes.
#echo off
echo Type in the name of your folder and hit enter.
set /P x=Please type the folder name here:
md %userprofile%\desktop\"%x%"
start %userprofile%\desktop\"%x%"
pause
rd %userprofile%\desktop\"%x%"
I expected the folder to open on the desktop and just get an error that the name is not recognized.
Please read answer on How to stop Windows command interpreter from quitting batch file execution on an incorrect user input? and the commends in batch code below for understanding why this code is much better for your task.
It is usually necessary to enclose the entire argument string in double quotes and not just parts of it as it can be seen below.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
echo Type in the name of your folder and hit ENTER.
:UserPrompt
set "Folder="
set /P "Folder=Please type the folder name here: "
rem Has the user entered a string at all?
if not defined Folder goto UserPrompt
rem Remove all double quotes of user input string.
set "Folder=%Folder:"=%"
rem Was not only one or more double quotes entered by the user?
if not defined Folder goto UserPrompt
rem Create the folder with suppressing the error message.
md "%UserProfile%\Desktop\%Folder%" 2>nul
rem Could the folder name be created at all which means the user
rem input string was valid and the folder did not exist already?
if errorlevel 1 goto UserPrompt
rem Open the just created folder on user's desktop.
start "" "%UserProfile%\Desktop\%Folder%"
pause
rd "%UserProfile%\Desktop\%Folder%"
endlocal
Instead of the command line
start "" "%UserProfile%\Desktop\%Folder%"
it is also possible to use
%SystemRoot%\explorer.exe "%UserProfile%\Desktop\%Folder%"
or use
%SystemRoot%\explorer.exe /e,"%UserProfile%\Desktop\%Folder%"
explorer.exe is an exception of general rule to enclose an entire argument string in double quotes. "/e,%UserProfile%\Desktop\%Folder%" would not work because in this case the argument string would be interpreted as folder with an invalid relative path to root directory of current drive instead of option /e with folder to open.
But Windows Explorer does not offer options to define window position and size. Whatever the user used the last time and is therefore most likely preferred by the user is used again by Windows Explorer on opening an Explorer window for a folder.
It would be of course possible with additional code to send to the just opened Explorer window being top-level foreground window a message for changing window position and size. See for example:
How can a batch file run a program and set the position and size of the window?
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 /?
if /?
md /?
pause /?
rd /?
rem /?
set /?
setlocal /?
start /?

Making a directory on a path stored inside a variable in batch file

I'm new in batch programming. The thing is I have a path and a new folder name in 2 variables, so I want to concatenate it and make a new folder in that result path. I tried many things but nothing worked. Please help
I tried this code
#echo off
setlocal EnableDelayedExpansion
set ver=project
set spath=d:\a\svn\
set path=!%spath%%ver%!
mkdir %path%
pause
endlocal
Do not use path as name for an environment variable because such an environment variable is defined already by default with a very important meaning, see the answers on What is the reason for 'sort' is not recognized as an internal or external command, operable program or batch file?
To concatenate two environment variable values just reference those two environment variables on assigning the value to one of the two environment variables or a new environment variable.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ProjectVersion=project"
set "SvnPath=d:\a\svn\"
set "ProjectPath=%SvnPath%%ProjectVersion%"
mkdir "%ProjectPath%"
pause
endlocal
See also answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? for the reason using set "variable=value" with double quotes around string value to variable assignment, i.e. around the argument string of command SET.
The commands SETLOCAL and ENDLOCAL would not be really necessary here.
Possible would be also:
#echo off
set "ProjectVersion=project"
set "SvnPath=d:\a\svn\"
set "ProjectPath=%SvnPath%%ProjectVersion%"
mkdir "%ProjectPath%" 2>nul
if not exist "%ProjectPath%\" echo Failed to create directory "%ProjectPath%" & pause & goto :EOF
The batch file above creates the directory with suppressing any error message by redirecting STDERR to device NUL. An error message is output if the directory already exists or it was not possible to create the directory because NTFS permissions denies folder creation for current user or in directory path there is a file with the name of a directory in path, e.g. there is a file with name project in directory d:\a\svn or there is a file svn in directory d:\a. The next command with a backslash appended to directory path checks if the directory exists after execution of command MKDIR and outputs an error message with PAUSE and next exiting batch file when the directory still does not exist.
Read also the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul and Single line with multiple commands using Windows batch file for an explanation of & operator.
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 /?
goto /?
if /?
mkdir /?
pause /?
set /?
setlocal /?
#echo off
setlocal EnableDelayedExpansion
set version=project
set spath=d:\a\svn\
set mypath=%spath%%version%
mkdir %mypath%
pause
endlocal
path is a reserved name - it defines the sequence of directories that is searched for an executable if the executable is not found in the current directory. If you change it, well - in short, gloom
ver is not a reserved name, but it is the name of a inbuilt utility and makes a poor choice for variable-name.
Your code was attempting to set your desired new pathname to the contents of the variable d:\a\svn\project. Since this variable is very unlikely to exist, you would have attempted to make a directory named nothing.
btw - there is no need to set mypath - md %spath%%ver% would work just as well. MD is a synonym of mkdir and is used more often.

Odd issue when feeding icacls an external variable

Good morning.
I am having an issue with a batch script I have. I have a program that feeds it a variable and I use that variable to create a folder and then apply Icalcs permissions on it. For some reason it will create the folder with the variable name but Icalcs will be blank where the variable should be. Here is the code -
set whodo=%2
set username=%whodo%
set path="\\example\shares\Student\%username%"
md %path%
md %path%\Desktop
md %path%\Contacts
md %path%\Favorites
md %path%\Links
md %path%\Music
md %path%\Pictures
md %path%\Saved Games
md %path%\Searches
md %path%\Video
md %path%\Documents
c:\windows\system32\icacls.exe %path% /T /C /inheritance:e /grant:r %username%:(OI)(CI)M
The %2 is pulling the variable from the program that runs this script, I was then putting the variable into another variable to see if that would make Icacls happy, but it doesn't. Without the variable pulled from the program this script works fine. I cannot figure out why the Path and Username variables work everywhere but Icacls. Is this some flaw icacls has?
Thanks
Open a command prompt window and run set to get output the list of predefined environment variables. For a description of each predefined environment variable see for example Wikipedia article about Windows Environment Variables.
The predefined environment variables USERNAME and PATH should not be modified in a batch file except there is a really good reason to do that.
Also be careful on using set variable="value" instead of set "variable=value" because in first case the double quotes are also assigned as part of the string value to the environment variable and perhaps existing trailing spaces/tabs, too. For a detailed description read the answers on
How to set environment variables with spaces?
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
And strings containing 1 or more spaces must be enclosed in double quotes as the space character is used as string separator if not found within a double quoted string. The name of the user could contain a space. The directory name Saved Games contains definitely a space.
I suggest to use this batch code:
rem Get name of user with surrounding double quotes removed.
set "whodo=%~2"
set "NameUser=%whodo%"
set "PathUser=\\example\shares\Student\%NameUser%"
rem Create directories for this user on server. With command extensions
rem enabled as by default the command MD creates the entire directory
rem tree if that is necessary. Therefore it is not necessary to create
rem separately the profile directory of the user first.
md "%PathUser%\Desktop"
md "%PathUser%\Contacts"
md "%PathUser%\Favorites"
md "%PathUser%\Links"
md "%PathUser%\Music
md "%PathUser%\Pictures"
md "%PathUser%\Saved Games"
md "%PathUser%\Searches"
md "%PathUser%\Video"
md "%PathUser%\Documents"
%SystemRoot%\System32\icacls.exe "%PathUser%" /T /C /inheritance:e /grant:r "%NameUser%:(OI)(CI)M"
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 %~2 (second argument without surrounding quotes).
cmd /? ... explains on last help page when double quotes are needed.
icacls /?
md /?
rem /?
set /?

Check and make list of jpg files if present to a text file using batch script

I have a project which has following steps:
Create list of jpg files in a folder (initially there is none).
Go to step 1 if the created text file is empty.
Start another program (this program needs the received jpg file as input) if the created list file in step 1 is not empty.
JPG file will be sent to this folder by another process.
I am new to using batch script and used the following code from input.
But this program is not starting another process as required in step 3 even after receiving JPG file.
What is wrong with my code?
#echo off
set "dir=E:\test"
set "file=%dir%\a.txt"
:start
dir/b *.jpg>a.txt
if "%~z1" == "" (
goto start
)
if "%~z1" == "0" (
goto start
)
if "%~z1" == "1" (
Start "" "C:\Users\vamsidhar muthireddy\Documents\Visual Studio 2010\Projects\database_test0\Debug\database_test0.exe"
)
Don't name a variable like an internal command. It is possible to name a variable dir although there is also the command DIR, but it is not advisable.
Don't name a label like an internal command. It is possible to name a label start although there is also the command START, but it is not advisable.
Why is it not advisable to name a variable or label like a command?
Well, for example if in future somebody wants to find where variable dir is used and the batch file contains also command DIR, or wants to rename label start by running a replace and batch file contains also command START, these actions become difficult as it must be analyzed in which context dir and start are used on each found occurrence.
Also syntax highlighting of batch file code is definitely not correct with commands DIR and START as the variable dir and the label start would be most likely also highlighted as commands.
The main coding mistake is %~z1 as this is replaced by file size of the file specified with its file name as first argument on calling the batch file if the batch file was called at all with a file name of an existing file. But this is not the case here. The intention here was getting size of the list file. Also if "%~z1" == "1" will be nearly never true. This condition becomes only true if the file specified as parameter has a file size of exactly 1 byte.
Here is a commented batch code which I think is more useful for the task:
#echo off
set "SourceDirectory=E:\test"
rem This loop is executed with a delay of 5 seconds between each loop run
rem until at least 1 file with extension JPG is found in the defined source
rem directory. Then the JPG file is processed and batch processing ends.
:Loop
echo Checking for a *.jpg file in %SourceDirectory% ...
if exist "%SourceDirectory%\*.jpg" goto ProcessFile
%SystemRoot%\System32\ping.exe 127.0.0.1 -n 6 >nul
goto Loop
:ProcessFile
for %%I in ("%SourceDirectory%\*.jpg") do (
echo Processing %%I ...
start "" "%USERPROFILE%\Documents\Visual Studio 2010\Projects\database_test0\Debug\database_test0.exe" "%%I"
)
rem Delete the created variable before exiting batch processing.
set "SourceDirectory="
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 /?
for /?
goto /?
if /?
ping /?
rem /?
set /?
start /?

Resources