I have a batch checking for a specific file like this:
if exist "C:\Program Files\App\App version number\file.exe" (
echo EXISTS
) else (
echo NOT EXIST!
)
I want to be able to check for the file.exe in any version so it might be in:
"C:\Program Files\App\App v.1\file.exe"
"C:\Program Files\App\App v.2\file.exe"
How can I skip the version number as a requirement inside the path?
Here is an example using the WHERE command with conditional operators.
where /Q /R "C:\Program Files\App" file.exe && echo found || echo not found
Might be a bit overkill but should work.
main.bat:
#echo off
for /f "tokens=*" %%i in ('sub.bat') do (
if "x%%i"=="x" (
echo "Not found!"
) ELSE (
echo "Found in %%i"
)
)
sub.bat:
#echo off
set your_path="C:\Your Path\"
cd /d %your_path%
for /r %%p in (file.exe) do echo %%p
Explanation:
The main batch is the one to execute. It reads the output of the sub batch and reacts properly.
Set the root for the search to the variable your_path. It will change the directory and then searches with an /Recursive loop through the current directory and looks for the file you set in the parenthesis. If the file is found, it will echo that to get read by the main file.
Feel free to ask further questions :)
setlocal
set AppDir=
for /d %%d in ("C:\Program Files\App\App v*") do if exist "%%d\file.exe" set "AppDir=%%d"
if defined AppDir (
echo EXISTS - it's in "%AppDir%"
) else (
echo NOT EXIST!
)
endlocal
(Update: Edited to put quotes around variables in case there's a filename that contains a special character such as &. Thanks to #aschipfl for pointing this out. On the other hand, there's no need to use %%~d instead of just %%d because %%d won't have any quotes anyway.)
Related
I've written a simple batch file to move .pdf files to certain folders located on a file system. Currently, the code checks to see if a folder with a company's name exists (P:\invoices\%company%). If the folder exists then the code checks to see if a subfolder called 2021 is located at P:\invoices\%company%\2021. If the 2021 folder already exists, the code moves the .pdf file to that 2021 folder.
However, if the 2021 subfolder does not exist, then the code is supposed to create a 2021 folder at P:\invoices\%company%\2021. I used the md command to do this but it creates a generic file called 2021 instead of a folder. Then the .pdf file disappears into thin air, presumably because it is moving it into a file instead of a folder.
Here is the code:
#echo off
for /r "C:\Users\me\Scan\*.pdf" %%G in (*.pdf) do set "name=%%~nG"
for /f "tokens=1-2 delims=-" %%i in ("%name%") do set "company=%%i"
if exist "P:\invoices\%company%" do (
if exist "P:\invoices\%company%\2021" do (
move /y "C:\Users\me\Scan\*.pdf" "P:\invoices\%company%\2021"
)
else do (
md "P:\invoices%\company%\2021"
move /y "C:\Users\me\Scan\*.pdf" "P:\invoices%\company%\2021"
)
)
What am I doing wrong?
#echo off
:: This ensures that the original environment is restored on termination
SETLOCAL
:: Use variable so year needs to be changed in only 1 place
set "year=2021"
:: And representing destination parent-directory
set "destparent=P:\invoices"
:: read the filenames from the tree
for /r "C:\Users\me\Scan\*.pdf" %%G in (*.pdf) do (
REM %%G has full filename, %%~nG the name part only
for /f "tokens=1 delims=-" %%i in ("%%~nG") do (
REM %%i has company name
REM Optional to auto-create company-directory begin
REM force Company directory to exist
MD "%destparent%\%%i" 2>nul >nul
REM Optional to auto-create company-directory end
REM If company directory truly exists
if exist "%destparent%\%%i\." (
rem force year subdirectory to exist
MD "%destparent%\%%i\%year%" 2>nul >nul
rem does subdirectory now exist?
if exist "%destparent%\%%i\%year%\." (
move /y "%%G" "%destparent%\%%i\%year%\"
) else (
echo "%destparent%\%%i\%year%" directory not found
)
) else (
echo "%destparent%\%%i" directory not found
)
)
)
[Untested - apply to dummy directories for verification]
OP code problems:
The for /r ... %%G will assign to name the name of the LAST file encountered, which will be the from the very last directory in the subtree that contains a file passing the name-mask *.pdf Then the value installed in name is only used to derive the company-name.
company is set up from the part before the first - in name. The part between the first and second - in name (or end of name) is assigned to %%j and never used. OP should consider the possibility that the actual company-name is hyphenated.
OP's code uses if ... DO ( (more than once). DO is illegal here and must be omitted.
OP's code uses else ... DO ( . DO is illegal here and must be omitted. The else keyword must be on the same physical line as the ) for the true code block (parenthesised sequence of statements)
The MOVE statements attempt to move ALL of the .pdf files in the selected subtree-rootdirectory to the destination, regardless of file's company-code or the fact that the selected company-code may be from the .pdf at the deepest level of the tree.
I've attempted to fix the code to do what I suspect the actual intention of the code is, being to move the .pdf files from the subtree to each file's appropriate destination\company\2021 directory, creating directories as necessary.
I will emphasise one again that this code is UNTRIED.
As a suggestion for testing, on a copy of the batch, I would replace each MD and MOVE statement with ECHO MD and ECHO MOVE respectively, and omit all of the redirection statements 2>nul and >nul (which are intended to suppress unwanted messages)
Finally, I'd insert a PAUSE line before the final goto :eof to permit the resultant proposed-list-of-changes from disappearing as I suspect that we may be dealing with a case of Heretical Clickitis.
Here's how I'd suggest you try the task:
As a batch-file:
#For /R "%UserProfile%\Scan" %%G In (*-*.pdf
) Do #For /F "Delims=-" %%i In ("%%~nG"
) Do #%SystemRoot%\System32\Robocopy.exe "%%~dpG." "P:\invoices\%%i\2021" "%%~nxG" /Mov 1>NUL
Or, as a single line entered in cmd:
For /R "%UserProfile%\Scan" %G In (*-*.pdf) Do #For /F "Delims=-" %i In ("%~nG") Do #%SystemRoot%\System32\Robocopy.exe "%~dpG." "P:\invoices\%i\2021" "%~nxG" /Mov 1>NUL
Just change the paths, %UserProfile%\Scan and P:\invoices, as needed.
[Edit /]
If you want you own code fixing, according to the comments I've already made, and to fix your two previously unmentioned typos md "P:\invoices%\company%\2021" and move /y "C:\Users\me\Scan\*.pdf" "P:\invoices%\company%\2021, which should have read md "P:\invoices\%company%\2021" and move /y "C:\Users\me\Scan\*.pdf" "P:\invoices\%company%\2021 respectively. Then this is how I'd suggest you could have fixed it:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
For /R "C:\Users\me\Scan" %%G In (*.pdf) Do (
Set "name=%%~nG"
SetLocal EnableDelayedExpansion
For /F "Delims=-" %%i In ("!name!") Do (
EndLocal
Set "company=%%i"
)
SetLocal EnableDelayedExpansion
If Exist "P:\invoices\!company!\" (
If Not Exist "P:\invoices\!company!\2021\" (
MD "P:\invoices\!company!\2021"
)
If Exist "P:\invoices\!company!\2021\" (
Move /Y "%%G" "P:\invoices\!company!\2021"
)
EndLocal
)
Pause
Note: As you are both creating and using variables within the same parenthesized code blocks, I have used delayed expansion to ensure that your updated variables are maintained throughout.
Please now compare my upper answer with your fixed version below it, and see why, I offered the much shorter and simpler solution initially.
I have Z: substituted to a network drive, eg:
subst Z: \\fc\c
xfile is a file (not a directory!) that exists in the root of the substituted drive. The below statement incorrectly echoes -exists-
if exist z:\xfile\nul echo -exists-
This makes xfile appear to be a directory, when it's really a file.
A non-substituted drive letter does not cause the problem. A subst to a non-network drive also does not cause the problem.
Is there a workaround to handle what looks like a subst or if-exist bug?
Here is a general construct which should work from your .BAT file argument, (this one assumes it is the first argument %1):
#Echo Off
For /F "Tokens=1-2 Delims=d" %%A In ("-%~a1") Do (
If "%%B" NEq "" (
Echo %1 is a directory
) Else If "%%A" NEq "-" (
Echo %1 is a file
) Else (
Echo %1 does not exist
)
)
Pause
Dont use the \Nul mechanism.
Better use this: (Simply add a backslash)
if exist "%ALLUSERSPROFILE%\" (
echo Folder exist
) else (
echo Folder does not exist
)
I often have to track down files at work, pulling a hundred or so out of a list of a thousand, so I created a batch file that would copy the files in a location that are listed in a csv in the batch files directory and then paste them in a folder on my desktop.
This worked, but I often have to do this for hundreds of files across a dozen or so directories, so I tried to modify it to include subdirectories. I'm having an issue getting it to work and I was wondering if the excellent people at StackOverflow could help. Thanks!
#echo on
set theDest="%USERPROFILE%\Desktop\Batch Copies %date:/=%"
set /p MY_TEXT=<FileList.csv
echo.%MY_TEXT%
set MY_TEXT=%MY_TEXT:"",""=,%
echo.%MY_TEXT%
if not exist %theDest% md %theDest%
pause
for /R %MY_TEXT% %%G IN (.) do (
for /F "skip=1 delims=" %%f in (FileList.csv) do (
if exist "%MY_TEXT%\%%f.*" (
copy "%MY_TEXT%\%%f.*" %theDest%
) else (
if exist "%MY_TEXT%\%%f" (
copy /R "%MY_TEXT%\%%f" %theDest%
) else echo "%MY_TEXT%\%%f" does not exist && echo 0 file^(s^) copied. && echo ERROR: %%f not found && echo. && pause)
)
)
echo. && echo. && echo Process Completed. &&echo.
pause
Part of the problem is I was just getting into batch when I wrote this and then left it and am trying to come back and figure out how everything works so I've probably messed it up more ways than one.
So the FOR loop has a /R option which will run the same command across all subdirectories.
In your case, I think you want:
for /R %%a in (.) do call :MyCopyFunction %%a
exit /B
:MyCopyFunction [%1 is the current directory]
echo My Current directory is %1
[Do All your code here, using %1 as the current directory]
exit /B
I don't understand what your script is doing in detail, so you still have to fill in the details.
But this shows you how to traverse the entire directory structure.
I would like use command batch to create list folder.
But the name of folder include symbol characters, I don't know how to use cmd batch
Ex: I would like create list folder
01.DOCUMENT
02.SOURCE
03.DESIGN
04.TEST
05.REPORT
06....
Input: Input root-directory(strfolder)
Then example use: mkdir %strfolder%\ (+ name folder 01.Ducment,...) but I don't know use
My current code:
#echo off
cls
set /p folderName=Enter project name:%=%
#echo %folderName%
SET mypath=%~dp0
rem echo %mypath:~0,-1%
set folder=%mypath%%folderName%
if exist %folder% (
echo "Folder already exists"
) else (
mkdir %folder%
rem mkdir %folder%\%1 %RELEASE% --> this line don't know how :D
echo %folder%\%^1%
)
pause
You'd need to quote your target if it contains symbols:
mkdir "%folder%"
(md is the same as mkdir)
Also:
mkdir "%folder%" 2>nul
will create the directory; the 2>nul suppresses the error message.
%release% appears from nowhere. You don't say what it is or where it comes from; then you REM it anyway. No iea of what is happening there.
Now if your directory-names are in a file then
for /f "delims=" %%i in (filename.txt) do echo %%i
should show you the names. If you want to create subdirectories using these names then
for /f "delims=" %%i in (filename.txt) do echo MD "%folder%\%%i"
should do that for you - well, would ECHO the command; remove the ECHO keyword to actually make the directory.
Note that virtually any character would be happy so long as it remains in the metavariable %%i used as a loop-control. Some less-frequently-used characters can present a problem within an ordingary %variable%.
If your data contains parentheses, then the parser may become confused about whether a parenthesis is part of the command or the data. Best to avoid parenthesised constructs if that is the case.
I am trying to do the following,
Verify.exe crawls a directory structure and checks files one by one for any defects. File is passed to verify.exe as a command line argument. If any defects are found in a file it prints an error code (one line string). If file is legitimate nothing is printed. I want to create a folder for each error code and copy the faulty file to the folder so I can take a look at it. If file has no errors nothing is done.
Files need to be checked are in D:\Test\docs\r1 - For testing purpose I have only one file in D:\Test\docs\r1.
::#echo off
CD D:\Test\doc\r1\
FOR /R %%a IN (*) DO (
ECHO %%a
FOR /F %%b IN ('D:\Test\doc\Verify.exe /i:"%%a"') do SET MyVAR=%%b
IF NOT "%MyVAR%" == "" (
ECHO "IF one"
IF EXIST D:\Test\doc\%MyVAR% (
ECHO "IF two"
MD D:\Test\doc\%MyVAR%
)
COPY %%a D:\Test\doc\%MyVAR%
)
SET MyVAR=
ECHO "------------------------"
)
I get the following echo on the command line.
D:\Test\doc>CD D:\Test\doc\r1\
D:\Test\doc\r1>FOR /R %a IN (*) DO (
ECHO %a
FOR /F %b IN ('D:\Test\doc\Verify.exe /i:"%a"') do SET MyVAR=%b
IF NOT "" == "" (
ECHO "IF one"
IF EXIST D:\Test\doc\ (
ECHO "IF two"
MD D:\Test\doc\
)
COPY %a D:\Test\doc\
)
SET MyVAR=
ECHO "------------------------"
)
D:\Test\doc\r1>(
ECHO D:\Test\doc\r1\A5 Incident Management.doc
FOR /F %b IN ('D:\Test\doc\Verify.exe /i:"D:\Test\doc\r1\A5 Incident Management.doc"') do SET MyVAR=%b
IF NOT "" == "" (
ECHO "IF one"
IF EXIST D:\Test\doc\ (
ECHO "IF two"
MD D:\Test\doc\
)
COPY D:\Test\doc\r1\A5 Incident Management.doc D:\Test\doc\
)
SET MyVAR=
ECHO "------------------------"
)
D:\Test\doc\r1\A5 Incident Management.doc
D:\Test\doc\r1>SET MyVAR=0x8004170b
"------------------------"
D:\Test\doc\r1>
Could someone help me in following issues..
The loop has run three times
No folders are created
It seems there is an issue in assigning exe command line output to MyVar
Thank you in advance
Assuming the output of your verify.exe command is correct, you probably should enable delayed expansion (at the top of your batch file):
SETLOCAL ENABLEDELAYEDEXPANSION
and use the ! syntax for variable used within a loop (replace %MYVAR% with !MYVAR!)
Otherwise, within the for-loop, %MYVAR% is only evaluated before the first run (where no value is defined).