How to get name off current directory - batch-file

I have been wanting my script to find a folder that starts with the string "onedrive...".
My code looks like this,
#echo off
set path="C:\Users\%USERNAME%"
if exist %path% (
cd "%path%\onedrive*"
echo %cd%
cd
)
pause
and the output I get is,
C:\Users\310176421\Backupscript\source
C:\Users\310176421\OneDrive for Business
where the first one is my .bat file directory and the second one is the line i want to make into a variable.
Any ideas?

Oh man don't do this, you are overwriting the system PATH. You have to use another name for that variable. And also you have to set it as local.
#echo off
SETLOCAL
REM blah blah
set _my_custom_path=....
ENDLOCAL

Here is a simple batch code which searches in profile directory of current user for a directory starting with string OneDrive and assigns the full path of first found folder without quotes to an environment variable output next before exiting batch.
#echo off
for /F "delims=" %%I in ('dir /AD /B /S "%USERPROFILE%\OneDrive*" 2^>nul') do (
set "OneDriveFolder=%%~I"
goto FoundFolder
)
echo Could not find a folder OneDrive.
goto :EOF
:FoundFolder
echo Found folder: %OneDriveFolder%
set "OneDriveFolder="
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 /?
for /?
goto /?
set /?
Note 1: C:\Users\%USERNAME% is not always equal %USERPROFILE% as the profile directory can be also on another drive than drive C: and Users is just the default parent directory for the user profiles on Windows Vista and later.
Note 2: 2^>nul redirects error message output by command DIR to stdout to device nul which means suppressing the error message in case of no directory starting with OneDrive is found case-insensitive. ^ escapes redirection operator > for command FOR to get 2>nul applied on command DIR.

Related

How can I find my error in the batch script?

The code below should archive some files by moving them into a subfolder. The batch file asks the user for the folder path. Then a subfolder should be created and if that was successful, it should move all files in the user input directory into the subdirectory. It works, but it closes although using pause. It does not output anything about a syntax error or anything at all. Please let me know if somebody notices something.
#echo off
SETLOCAL EnableDelayedExpansion
echo Insert path:
set /p path=
echo the path is %path%
cd %path%
echo The files will be moved to a new folder
pause
mkdir %path%\archived_files
IF EXIST "archived_files" (
for /f %%A in ('DIR /A /D /B') do (
echo %%A && move /Y %path%\%%A %path%\archived_files)
echo Folder "archived_files" created or already exists
) else ( echo Folder "archived_files" does not exist )
echo the files have been transferred
pause
ENDLOCAL
I suggest to use this batch file for the file moving task.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "BatchFileName=%~nx0"
set "BatchFilePath=%~dp0"
set "UserPath=%~1"
if defined UserPath goto ChangeFolder
:UserPrompt
set "UserPath="
set /P "UserPath=Enter path: "
rem Has the user not entered a string?
if not defined UserPath goto UserPrompt
rem Remove all double quotes from input string.
set "UserPath=%UserPath:"=%"
rem Has the user entered just one or more double quotes?
if not defined UserPath goto UserPrompt
:ChangeFolder
pushd "%UserPath%" 2>nul || (echo Folder "%UserPath%" does not exist.& goto UserPrompt)
for /F "eol=| delims=" %%I in ('dir /A-D /B 2^>nul') do goto CreateSubfolder
echo The folder does not contain any file to archive.& goto EndBatch
:CreateSubfolder
md "archived_files" 2>nul
if not exist "archived_files\" echo Failed to create subfolder: "archived_files"& goto EndBatch
rem It must be avoided that the currently running batch file is moved too.
set "ExcludeFileOption="
for %%I in ("%UserPath%\") do set "CurrentFolderPath=%%~dpI"
if "%CurrentFolderPath%" == "%BatchFilePath%" set "ExcludeFileOption= /XF "%BatchFileName%""
rem The command MOVE used with wildcard * does not move hidden files. A FOR loop
rem with MOVE is slow in comparison to usage of ROBOCOPY to move really all files.
rem The ROBOCOPY option /IS can be removed to avoid moving same files existing
rem already in the subfolder archived_files from a previous batch execution.
echo The files are moved to a new folder.
%SystemRoot%\System32\robocopy.exe . archived_files%ExcludeFileOption% /MOV /R:2 /W:5 /IS /NDL /NFL /NJH /NJS
if not errorlevel 2 if errorlevel 1 echo All files are moved successfully.
:EndBatch
popd
endlocal
pause
The batch file can be started with a a folder path as argument. So it is possible to right click on the batch file and click in opened context menu in submenu Send to on item Desktop (create shortcut). The .lnk file created on the user´s desktop can be renamed now also via context menu or key F2 to whatever name is useful like Archive files. Then the shortcut file can be cut with Ctrl+X and pasted with Ctrl+V in the folder %APPDATA%\Microsoft\Windows\SendTo to have in Send to context submenu the menu item Archive files. This makes it possible to right click on a folder and click in opened context menu in submenu Send to on Archive files to run the batch file without the need to enter a folder path manually.
The batch file prompts the user for the path if not started with a folder path as first argument or the folder cannot be found at all. This user prompt is done using a safe method. The batch file makes the passed or entered folder temporarily the current folder for the remaining commands using PUSHD and POPD instead of CD to work also with UNC paths.
There is checked next if the folder contains any file at all. Otherwise the user is informed that the directory does not contain files to archive and batch file ends without any further action.
The file movement is done with ROBOCOPY for the reasons described in a remark in the batch file which requires Windows Vista or a newer Windows version or Windows Server 2003 or a newer Windows server version.
I recommend to see also:
Debugging a batch file which answers your question.
What is the reason for "X is not recognized as an internal or external command, operable program or batch file"? It explains why path as name for the environment variable to assign the user entered path is a really bad idea.
How to stop Windows command interpreter from quitting batch file execution on an incorrect user input? It explains the reasons for using the additional code to evaluate the string entered by the user.
Why is no string output with 'echo %var%' after using 'set var = text' on command line? It explains the recommended syntax for the (re)definition of an environment variable and why using this syntax.
Syntax error in one of two almost-identical batch scripts: ")" cannot be processed syntactically here describes several common issues made by beginners in batch file coding like not enclosing a file/folder path in double quotes.
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 %~nx0, %~dp0 and %~1 whereby argument 0 is always the batch file itself.
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
md /?
pause /?
popd /?
pushd /?
rem /?
robocopy /?
set /?
setlocal /?
Other useful documentations used to write this code:
single line with multiple commands using Windows batch file
the Microsoft documentations for the used Windows Commands
the SS64 documentations for the used Windows CMD commands, especially:
ROBOCOPY.exe
ROBOCOPY Exit Codes
the Microsoft documentation about Using command redirection operators
and the SS64 documentation How-to: Redirection
Note: 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 with %ComSpec% /c and the command line within ' appended as additional arguments.

How to find and select newest file in a directory and restore with SQLRestore?

I want to make a batch or cmd file to automatically select the latest file in the directory D:\Romexis_Bilder\romexis_SQL_Backup. These are ZIP SQL backup files that are generated two times daily in the format yymmddhhmm.zip, e.g Romexis_db201805271200.zip on a server running Windows 2016 Server.
The latest added file to the directory (result of FOR /F) should then be used in SQL RESTORE (backup and ftp program Windows).
The idea was to use the FOR command
My draft:
Go into the directory:
pushd "D:\Romexis_Bilder\romexis_SQL_Backup"
Find the latest file. (I don't really know how to set the parameters here.)
for /f "tokens=*" %% in ('dir /D:\Romexis_Bilder\romexis_SQL_Backup /od') do set newest=%%D:\Romexis_Bilder\romexis_SQL_Backup
The result of FOR should be used in *.zip
cd C:\Program Files (x86)\Pranas.NET\SQLBackupAndFTP\
SqlRestore D:\Romexis_Bilder\romexis_SQL_Backup\*.zip -db Romexis_db -srv .\ROMEXIS -pwd password disconnect Romexis_db
I stuck with FOR, but don't know if there would also be another possibility.
I don't know if the last command line in question is really correct. I have some doubts output this line.
But this code can be used to get the name of the newest *.zip file according to last modification date without path.
#echo off
set "BackupFolder=D:\Romexis_Bilder\romexis_SQL_Backup"
for /F "eol=| delims=" %%I in ('dir "%BackupFolder%\Romexis_db*.zip" /A-D-H /B /O-D /TW 2^>nul') do set "NewestFile=%%I" & goto DatabaseRestore
echo ERROR: Could not find any *.zip backup file in folder:
echo "%BackupFolder%"
echo/
pause
goto :EOF
:DatabaseRestore
cd /D "%ProgramFiles(x86)%\Pranas.NET\SQLBackupAndFTP"
SqlRestore.exe "%BackupFolder%\%NewestFile%" -db Romexis_db -srv .\ROMEXIS -pwd password disconnect Romexis_db
echo/
pause
FOR executes in a separate command process started with cmd.exe /C in background the command line:
dir "D:\Romexis_Bilder\romexis_SQL_Backup\*.zip" /A-D-H /B /O-D /TW 2>nul
DIR outputs to handle STDOUT of background command process
only names of non hidden files because of /A-D-H (attribute not directory and not hidden)
in bare format because of /B just the file name with file extension, but without file path
sorted reverse (newest first) by date because of /O-D
using write time (last modification time) because of /TW
in directory D:\Romexis_Bilder\romexis_SQL_Backup matching the pattern Romexis_db*.zip.
I recommend running this command line in a command prompt window to see at least once what DIR outputs.
DIR would output an error message to handle STDERR in case of no *.zip file found or the directory does not exist at all. This error message is suppressed by redirecting it to device NUL.
Read also the Microsoft article 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.
FOR captures the output written to STDOUT and processes the output line by line with ignoring empty lines which do not occur here because of DIR with option /B does not output empty lines.
FOR with option /F would ignore lines starting with a semicolon by default. For that reason end of line character is redefined with eol=| from ; to a vertical bar which file names can't contain. eol=| would not be required in this case because of file name pattern Romexis_dbYYYMMDDhhmm.zip making it unlikely that a file name starts with a semicolon.
FOR with option /F would split up the lines into substrings using space/tab as delimiter and would assign for each line only first space/tab delimited string to specified loop variable I. This line splitting behavior is disabled by specifying an empty list of delimiters with delims=. delims= would not be required in this case because of file name pattern Romexis_dbYYYMMDDhhmm.zip making it unlikely that a file name contains a space character.
The name of the file output first by DIR which is the newest ZIP file in specified directory is assigned to environment variable NewestFile. And next the FOR loop is exited with a jump to label DatabaseRestore as all other file names output by DIR are of no interest for this task.
The command lines below the FOR command line are executed only if there is no *.zip file in specified directory which report this unexpected error case.
It would be also possible to use the DIR command line below in batch file because of file name pattern Romexis_dbYYYMMDDhhmm.zip:
dir "%BackupFolder%\Romexis_db*.zip" /A-D-H /B /O-N 2^>nul
The same command line for execution from within a command prompt window:
dir "D:\Romexis_Bilder\romexis_SQL_Backup\*.zip" /A-D-H /B /O-N 2>nul
The order of the file names in output is here reverse by name which results in printing first the Romexis_db*.zip with newest date/time in file name thanks to date/time format YYYMMDDhhmm.
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 /?
dir /?
echo /?
for /?
goto /?
pause /?
set /?
See also:
Where does GOTO :EOF return to?
Single line with multiple commands using Windows batch file
#Mofi
Thanks you for all your work it helped a lot!
As you advised I used each command in command prompt first to see the outputs (adapted batch %%I to cmd %I and vice versa)
I'm now able to find the newest file in D:\Romexis_Bilder\romexis_SQL_Backup the result is processed an taken as variable into the restore of the database which is done with One-Click SQL Restore https://sqlbackupandftp.com/restore
I did some modification in syntax of your commands O:D since „- „ excludes, removed attribute /TW because it was only listing backups from 2017.
#echo off
set "BackupFolder=D:\Romexis_Bilder\romexis_SQL_Backup"
for /F "eol=| delims=" %I in ('dir "%BackupFolder%\Romexis_db*.zip" /A-D-H /B /O:D 2^>nul') do set "NewestFile=%I" & goto DatabaseRestore
echo ERROR: Could not find any *.zip backup file in folder:
echo "%BackupFolder%"
echo/
pause
goto :EOF
:DatabaseRestore
cd /D "%ProgramFiles(x86)%\Pranas.NET\SQLBackupAndFTP"
SqlRestore.exe "%BackupFolder%\%NewestFile%" -db Romexis_db -srv .\ROMEXIS -pwd password
echo/
pause
Maybe the ^ in 'dir "%BackupFolder%\Romexis_db*.zip" /A-D-H /B /O:D 2^>nul' is not correct in CMD but didn‘t seem affect the result.
It was really advance! Now the GUI of One-Click SQL Restore opens with the newest *zip . The only thing that I still need to get out, is the syntax in command prompt for the restore, now i still need to click on the restore button of the GUI. Or try it over Microsoft Visual Studio SQL or command line tool.
#MOFI no modifications are made to files from 2017 or other files at all, files are not overwritten or modified later, a new file is always created by the back up program 2 times a day with the naming romexis_dbYYYMMDDhhmm.ziptwo times a day. Will try /O-N
THANKS a lot fo you input

change to directory after searching for the file via DIR

Outcome is to change to directory after searching for the file via DIR through cmd
Location of file is C:\Folder
is the following code possible?
set /a variable= dir document.doc /s /p
cd %%variable%%
Change directory to C:\Folder
try this:
for /f "delims=" %%# in ('dir document.doc /s /b') do (
set "new_dir=%%~dp#"
)
cd /d "%new_dir%"
Run in a command prompt window set /? and read the output help carefully from first to last page.
set /A is for evaluating an arithmetic expression. So the string after set /A is interpreted by Windows command line interpreter as arithmetic expression (formula).
set /a variable= dir document.doc /s /p
This command line outputs on execution the error message missing operator because dir is interpreted as a variable name and also document.doc both most likely not existing and therefore replaced by 0 on evaluating the expression. But cmd.exe expects an operator between those two environment variable names and as there is none like / before variable s, the error message is output.
It is not possible to assign possible multi-line output of a command line like dir document.doc /s /p to an environment variable with command SET.
In a batch file you can use this code:
#echo off
for /R %%I in ("document*.doc") do cd /D "%%~dpI" & goto FoundFile
echo Could not find any document*.doc in %CD% or its subdirectories.
pause
goto :EOF
:FoundFile
echo Found a file document*.doc in directory %CD%.
pause
Command FOR searches for any non hidden file matching the pattern document*.doc in current directory and all non hidden subdirectories. A wildcard character like * or ? must be specified to run a search for a file. If a file is found, the command CD is executed to change to directory of the file and the loop is exited with a jump to a label.
Another solution to really search only for file document.doc:
#echo off
for /F "delims=" %%I in ('dir "document*.doc" /A-D /B /S 2^>nul') do cd /D "%%~dpI" & goto FoundFile
echo Could not find file document.doc in %CD% or its subdirectories.
pause
goto :EOF
:FoundFile
echo Found file document.doc in directory %CD%.
pause
This example shows how to run a command line like dir "document*.doc" /A-D /B /S 2>nul in a separate command process started by FOR with cmd.exe /C with capturing all output lines written to handle STDOUT while in this case redirecting an error message written to handle STDERR to device NUL to suppress it.
The captured output is next processed by FOR line by line with skipping with default options all empty lines and lines starting with a semicolon and splitting up each line into substrings (tokens) using space and tab as delimiters with assigning only first substring to specified loop variable I. This line splitting behavior is disabled by using "delims=" which defines an empty list of delimiters and so no line splitting is possible anymore. In this case it is impossible that a line output by DIR starts with ; and so we don't need to care about eol (end of line) option.
%%~dpI expanding to just drive and path of current file name with path can be also assigned to an environment variable for example with set "FilePath=%%~dpI". And the environment variable FilePath can be referenced in rest of the batch file either with immediate expansion using %FilePath% or with delayed expansion using !FilePath! enclosed the entire argument string containing this variable reference in double quotes for working also for file paths containing a space or one of these characters: &()[]{}^=;!'+,`~
Both batch codes always changes to first found document*.doc respectively document.doc file and ignoring all other files matching the pattern respectively with same name perhaps also found by FOR or DIR in other directories in searched directory tree. The first solution is faster on a large directory tree needs to be searched for the file. But first solution ignores hidden subdirectories and can change to a directory containing for example document_1.doc instead of document.doc.
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 /?
dir /?
echo /?
for /?
goto /?
pause /?
Read also the Microsoft article 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.

Batch file command to select newest folder except if specific name

We have a batch file to create a variable from the folder name of the newest folder created in a specific location. As newer versions of this software is released the version number (folder name also) i.e. 10.0, 10.1, 10.2, 10.3 folder is created in this directory. Until now this has worked without hitch, however in the last update they decided to add a folder called Install in this same directory.
Is it possible to change the following script to ignore the Install folder and select the newest created folder name instead:
SET TABVER="C:\Program Files\Tableau\Tableau Server\"
FOR /F "delims=" %%i IN ('dir %TABVER% /b /ad-h /t:c /od') DO SET VERSION=%%i
SET TABCMD="C:\Program Files\Tableau\Tableau Server\%VERSION%\bin\tabcmd.exe"
This batch code could be used:
set "TABVER=C:\Program Files\Tableau\Tableau Server\"
for /F "delims=" %%I in ('dir "%TABVER%" /B /AD-H /T:C /O-D 2^>nul') do if /I not "%%I" == "Install" set "VERSION=%%I" & goto FoundVersion
echo Error: There is no version subfolder in probably not already existing folder:
echo/
echo %TABVER%
echo/
pause
goto :EOF
:FoundVersion
set TABCMD="%TABVER%%VERSION%\bin\tabcmd.exe"
rem Other commands using TABCMD
The DIR option /od is modified to /O-D to get the list of subdirectories in reverse order output by command DIR with newest directory first and oldest directory last.
The additional IF command compares case-insensitive the current directory name with the string Install. Only if the directory name is not Install the directory name is assigned to environment variable VERSION and the loop is exited without processing all other directory names with a jump to label FoundVersion.
I added an error output in case of C:\Program Files\Tableau\Tableau Server does not exist at all, contains no subdirectories or contains just Install and with halting batch file execution until user presses any key and then exiting the batch file processing.
Read also the Microsoft article 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.
See also How to set environment variables with spaces? In general it is better to use the command line set "variable=value" and reference the environment variable with "%variable%" instead of using set variable="value" and reference the environment variable with just %variable%. Look on %TABVER% references why it makes sense not having assigned a folder path with the double quotes to an environment variable.
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 /?
for /?
goto /?
if /?
pause /?
rem /?
set /?
Read also single line with multiple commands using Windows batch file and Where does GOTO :EOF return to?

get filename in the batch file each time a new file is placed

My requirement is - i need to read the filename from an input folder say - C:\Encrypt\In and pass it to the command java.exe -jar D:\SYS\src\PI\IN\Cryptage.jar -rc4 -crypt D:\SYS\src\PI\IN\Decrypt\ D:\src\PI\IN\Encrypt\ %VAR1%%VAR2%
i tried doing the one below - but no luck
set VAR1=FOR /R C:\Encrypt\In %F in (*.*) do echo %~nF
set VAR2=ABCD
echo %VAR1%%VAR2% (concatenate the filename with "ABCD" as constant)
java.exe -jar D:\SYS\src\PI\IN\Cryptage.jar -rc4 -crypt D:\SYS\src\PI\IN\Decrypt\ D:\src\PI\IN\Encrypt\ %VAR1%%VAR2%
(pass it here - so that each time a file comes in the input directory the variables can pick up the file names dynamically through the variables)
echo %VAR1%%VAR2% is not working.
Thanks anyway - i achieved it through this :- cd C:\Encrypt\In\ for %%f in (.) do ( rem echo %%~nfAPSI set v=%%~nfAPSI ) echo %v%
Here is a commented batch code for your task:
#echo off
set "ScanFolder=C:\Encrypt\In"
rem The loop runs command DIR to get a list of files with archive attribute set.
rem Directories are ignored even if archive attribute is set on a directory.
rem On each file with archive attribute currently set the archive attribute
rem is removed from file and then the command is started to process the file.
rem After all files with archive attribute were processed, the batch file
rem waits 5 seconds before scanning the folder again. The loop is infinite
rem and can be breaked only by pressing Ctrl+C or closing command prompt
rem window to stop command line interpreter.
:Loop
for /F "delims=" %%F in ('dir /AA-D /B "%ScanFolder%" 2^>nul') do (
%SystemRoot%\System32\attrib.exe -A "%ScanFolder%\%%~nxF"
java.exe -jar D:\SYS\src\PI\IN\Cryptage.jar -rc4 -crypt D:\SYS\src\PI\IN\Decrypt\ D:\src\PI\IN\Encrypt\ "%ScanFolder%\%%~nxF"
)
%SystemRoot%\System32\ping.exe -n 6 127.0.0.1>nul
goto Loop
java.exe should be called with full path enclosed in double quotes if possible as in this case command line interpreter would not always need to search for it in the folders of environment variable PATH.
Note: The batch file calls the new file with full path, file name and extension without anything appended. Of course you can replace %%~nxF at end of line calling java.exe also with %%~nFABCD if this is necessary in your environment.
For an explanation of the used commands and how they work in detail open a command prompt window and execute following commands to see the help of those commands:
attrib /?
dir /?
for /?
ping /?

Resources