I have a batch file which looks like this:
set OWNPATH = %~dp0
for /r %OWNPATH% %%F in (*.ocx) do ( echo %%F )
It correctly lists all OCX files in the same folder when I start it, but lists the OCX files in
C:\Windows\System32
when I right-click it and select "Run as administrator".
How can I fix that? The script generally needs admin rights.
Your set is setting %OWNPATH % (note the space between OWNPATH and the =). Therefore %OWNPATH% (with no space) is not defined, and for /r %OWNPATH% %%F ... gets expanded to for /r %%F, and the for loop ends up looking in the current directory (which is C:\Windows\System32 when run as administrator).
Get in the habit of doing your assignments like this to avoid that common mistake:
set "OWNPATH=%~dp0"
Related
I'm developing a stack of Windows Batch scripts (.bat) which are subsequently converted to self-extracting executabled.
Currently I'm facing a really strange problem. I create this self-extracting executable, which, after extracting all the files, will launch the main wrapper, (SETUP.bat). The whole stack of the scripts gets running and everything goes right until some point.
One part of the stack has to commit some files with UWFMGR, and I have a loop for like this:
SETLOCAL EnableDelayedExpansion
FOR /F usebackq "tokens=*" %%F IN ("DIR /S /B /A-D") DO (
uwfmgr file commit "%%F"
)
If I run the executable, the execution of the stack does not recognize the command UWFMGR
I stopped the execution of the script, and went with the same CMD, (which it's launched by the executable), to the System32 folder to check if the UWFMGR is there. I did a DIR "uwfmgr.exe", and it's not there. But if I go with another CMD (a new one) the command is there. I even went with a file explorer to verify it and it's completely there but somehow the CMD which it's being launched by the executable cannot recognize it.
I have tried to specify the whole path in the loop like this "C:\Windows\System32\UWFMGR.exe" and it doesn't even work.
The funny thing is that if run this script it works and commits all the files required.
SETLOCAL EnableDelayedExpansion
FOR /F usebackq "tokens=*" %%F IN ("DIR /S /B /A-D") DO (
uwfmgr file commit "%%F"
)
Does anyone have any idea of why this is happening?
Check the output of the command and the errorlevel, it's 9009 (the file/command does not exist)
Do an echo to check the command I'm passing through the loop, the command is OK
I expect the executable to do the whole stack and commit the files but the executable does not recognize UWFMGR command. I use other commands in my stack and I didn't have any problem.
64-bit Windows has two system32 folders. Windows\system32 is the real folder used by 64-bit applications. 32-bit applications are automatically redirected to Windows\Syswow64 when they access system32. There is a backdoor you can use to access the real system32 folder.
You should use if exist and set to find and store a usable path:
#echo off
set app=%windir%\system32\UWFMGR.exe
set appalt=%windir%\sysnative\UWFMGR.exe
if not exist "%app%" if exist "%appalt%" set app=%appalt%
echo.I will use %app%
UWFMGR seems to be an optional feature and is probably not present by default on most machines.
I solved it after finding out the exe was created as 32bits. I had to create as 64 bits in order to make it work. Now the executable is able to use the UWFMGR.
Thank you everyone for your answers and have a nice day.
I'm using this 7sfx module, just in case anyone's wondering: "7zsd_All_x64.sfx"
I have a lot of courses in subfolders that I have downloaded under (C:\Users\[username]\AppData\Local\lynda.com\Lynda.com Desktop App\offline\ldc_dl_courses) and I want to run this command on all subfolders under ldc_dl_courses but I have some problems creating a batch file to run it.
LyndaDecryptor /D “C:\Users\[username]\AppData\Local\lynda.com\Lynda.com Desktop App\offline\ldc_dl_courses\143455” /DB “C:\Users\[username]\AppData\Local\lynda.com\Lynda.com Desktop App\db.sqlite” /OUT “C:\Users\[username]\AppData\Local\lynda.com\Lynda.com Desktop App\offline\ldc_dl_courses\mp4”
I tried this but it didn't work
FOR /D %G IN ("C:\Users\salah\AppData\Local\lynda.com\Lynda.com Desktop App\offline\ldc_dl_courses") DO LyndaDecryptor /D "C:\Users\salah\AppData\Local\lynda.com\Lynda.com Desktop App\offline\ldc_dl_courses\%G" /DB "C:\Users\salah\AppData\Local\lynda.com\Lynda.com Desktop App\db.sqlite" /OUT "C:\Users\salah\AppData\Local\lynda.com\Lynda.com Desktop App\offline\ldc_dl_courses\mp4"
I suggest using following batch file for this task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "LyndaAppFolder=%LocalAppData%\lynda.com\Lynda.com Desktop App"
set "CoursesFolder=%LyndaAppFolder%\offline\ldc_dl_courses"
for /D %%I in ("%CoursesFolder%\*") do if /I not "%%I" == "%CoursesFolder%\mp4" LyndaDecryptor.exe /D "%%I" /DB "%LyndaAppFolder%\db.sqlite" /OUT "%CoursesFolder%\mp4"
endlocal
It is unclear for me if mp4 in courses folder is a folder or file. I suppose it is a folder which should be skipped on processing all non hidden subfolders in courses folder which is the reason for the additional case-insensitive IF condition.
The command FOR searches because of /D for non hidden directories in specified directory matching the wildcard pattern * and assigns the name of a found directory with full path without surrounding double quotes to loop variable I. The name of a found directory would be assigned to loop variable I without path if just * would be used in round brackets because of current directory is the directory containing the courses directories.
I suppose that LyndaDecryptor is an executable with file extension .exe and appended the file extension on last but one command line. Best would be to specify LyndaDecryptor with full path and with file extension as in this case Windows command interpreter has not to search for an executable or script with that file name on each iteration of the loop.
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 /?
if /?
set /?
setlocal /?
See also Wikipedia article about Windows Environment Variables for predefined environment variable LOCALAPPDATA used in the batch file using CamelCase notation for better readability as environment variables are not case-sensitive on Windows in comparison to FOR loop variables which are case-sensitive.
FOR /D %G IN ("C:\Users\[u]\AppData\Local\lynda.com\Lynda.com Desktop App\offline\ldc_dl_courses\*") DO LyndaDecryptor /D "%G" /DB "C:\Users\[u]\AppData\Local\lynda.com\Lynda.com Desktop App\db.sqlite" /OUT "C:\Users\[u]\AppData\Local\lynda.com\Lynda.com Desktop App\offline\mp4"
this is the following working solution
I have some folders with different names. Each folder has a specific structure as listed below:
Folder1
Contents
x64
Folder1.aaxplugin
TransVST_Fixer.exe
Folder 2
Contents
x64
Folder 2.aaxplugin
TransVST_Fixer.exe
There are two files within each subfolder x64. One file has the same name as the folder two folder levels above. The other file is an .exe file whose name is the same in all folders.
Now I need to run file with file extension aaxplugin on each specific .exe file. It would be obviously very time consuming opening each and every single folder and drag & drop each file on .exe to run it on this file.
That's why I am trying to create a batch script to save some time.
I looked for solutions here on Stack Overflow. The only thing I have found so far was a user saying this: When I perform a drag & drop, the process 'fileprocessor.exe' is executed. When I try to launch this exe, though, CMD returns error ('not recognized or not batch file' stuff).
How can I do this?
UPDATE 12/22/2015
I used first a batch file with following line to copy the executable into x64 subfolder of Folder1.
for /d %%a in ("C:\Users\Davide\Desktop\test\Folder1\*") do ( copy "C:\Program Files\Sugar Bytes\TransVST\TransVST_Fixer.exe" "%%a\x64\" 2> nul )
After asking here, I tried the following script:
for /f "delims=" %%F in ('dir /b /s x64\*.aaxplugin') do "%%~dpFTransVST_Fixer.exe" "%%F"
Unfortunately, the output is as following
C:\Users\Davide\Desktop>for /F "delims=" %F in ('dir /b /s x64\*.aaxplugin') do "%~dpFTransVST_Fixer.exe" "%F"
The system cannot find the file specified.
Try the following batch code:
#echo off
setlocal EnableDelayedExpansion
for /R "%USERPROFILE%\Desktop\test" %%F in (*.aaxplugin) do (
set "FilePath=%%~dpF"
if not "!FilePath:\x64\=!" == "!FilePath!" "%ProgramFiles%\Sugar Bytes\TransVST\TransVST_Fixer.exe" "%%F"
)
endlocal
The command FOR with option/R searches recursive in all directories of directory %USERPROFILE%\Desktop\test being expanded on your machine to C:\Users\Davide\Desktop for files with file extension aaxplugin. The loop variable F contains on each loop run the name of the found file with full path without surrounding double quotes.
The drive and path of each found file is assigned to environment variable FilePath.
Next a case-sensitive string comparison is done between file path with all occurrences of string \x64\ case-insensitive removed with unmodified file path.
Referencing value of environment variable FilePath must be done here using delayed expansion because being defined and evaluated within a block defined with ( ... ). Otherwise command processor would expand %FilePath% already on parsing the entire block resulting in a syntax error on execution because string substitution is not possible as no environment variable FilePath defined above body block of FOR loop.
The strings are not equal if path of file contains a folder with name x64. This means on provided folder structure that the file is in folder x64 and not somewhere else and therefore the application is executed next from its original location to fix the found *.aaxplugin file.
The line with IF is for the folder structure example:
if not "C:\Users\Davide\Desktop\test\Folder1\Contents" == "C:\Users\Davide\Desktop\test\Folder1\Contents\x64\"
if not "C:\Users\Davide\Desktop\test\Folder 2\Contents" == "C:\Users\Davide\Desktop\test\Folder 2\Contents\x64\"
So for both *.aaxplugin files the condition is true because the compared strings are not identical
Also possible would be:
#echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%F in ('dir /A-D /B /S "%USERPROFILE%\test\*.aaxplugin" 2^>nul') do (
set "FilePath=%%~dpF"
if not "!FilePath:\x64\=!" == "!FilePath!" "%ProgramFiles%\Sugar Bytes\TransVST\TransVST_Fixer.exe" "%%F"
)
endlocal
But command DIR is not really necessary as it can be seen on first provided code.
But if the application TransVST_Fixer.exe for some unknown reason does its job right only with directory of file being also the current directory, the following batch code could be used instead of first code using the commands pushd and popd:
#echo off
setlocal EnableDelayedExpansion
for /R "%USERPROFILE%\test" %%F in (*.aaxplugin) do (
set "FilePath=%%~dpF"
echo !FilePath!
if /I "!FilePath:~-5!" == "\x64\" (
pushd "%%~dpF"
"%ProgramFiles%\Sugar Bytes\TransVST\TransVST_Fixer.exe" "%%~nxF"
popd
)
)
endlocal
There is one more difference in comparison to first code. Now the last 5 characters of path of file are compared case-insensitive with the string \x64\. Therefore the file must be really inside a folder with name x64 or X64. A folder with name x64 or X64 anywhere else in path of file does not result anymore in a true state for the condition as in first two batch codes.
But if for some unknown reason it is really necessary to run the application in same folder as the found *.aaxplugin and the directory of the file must be the current directory, the following batch code could be used:
#echo off
setlocal EnableDelayedExpansion
for /R "%USERPROFILE%\test" %%# in (*.aaxplugin) do (
set "FilePath=%%~dp#"
if /I "!FilePath:~-5!" == "\x64\" (
pushd "%%~dp#"
"%%~dp#TransVST_Fixer.exe" "%%~nx#"
popd
)
)
endlocal
The path of the file referenced with %%~dpF always ends with a backslash which is the reason why there is no backslash left of TransVST_Fixer.exe (although command processor could handle also file with with two backslashes in path).
In batch code above character # is used as loop variable because %%~dp#TransVST_Fixer.exe is easier to read in comparison to %%~dpFTransVST_Fixer.exe. It is more clear for a human with using # as loop variable where the reference to loop variable ends and where name of application begins. For the command processor it would not make a difference if loop variable is # or upper case F.
A lower case f would work here also as loop variable, but is in general problematic as explained on Modify variable within loop of batch script.
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 /?
echo /?
endlocal /?
for /?
if /?
popd /?
pushd /?
set /?
setlocal /?
Your question isn't quite clear, but it seems, something like this should work:
for /f "delims=" %%f in ('dir /b /s X64\*.ext') do "%%~dpfMyExe.exe" "%%f"
Maybe you have to change directory to each folder (depends on your .exe):
for /f "delims=" %%d in ('dir /B /ad') do (
pushd "%%d"
for /f "delims=" %%f in ('dir /b "contents\x64\*.ext"') do (
cd Contents\x64
MyExe.exe "%%f"
)
popd
)
Assuming:
The Directory structure is fixed and the files are indeed in a subfolder contents\X64\.
MyExe.exe is the same (name) in every folder.
There is only one file *.ext in every folder.
I'll give you the script I created for doing so, hope it works for you
for /d %%d IN (./*) do (cd "%%d/Contents/x64" & "../../../TransVST_Fixer.exe" "%%d" & cd "/Program Files (x86)\Common Files\Avid\Audio\Plug-Ins")
Please note that I placed the fixer inside the root folder so I just have to copy it once. You have to place it inside your root folder and execute it. What it does:
iterate over each folder
for each one it enters /Contents/x64, executes the fixer (wich is 3 levels above) and after that returns to the original folder.
If you have your plugins in a different folder, you just have to change this part replacing the path for the one you have your plugins in.
cd "/Program Files (x86)\Common Files\Avid\Audio\Plug-Ins"
REMEMBER to place the script on that folder. For this example I place my script on the folder "/Program Files (x86)\Common Files\Avid\Audio\Plug-Ins" and run it (as a .bat).
PS: the fixer will place the fixed plugins in "C:\Users\Public\modified" (just read the screen while executing, it gives you the new files path. If you want to move them to the right path, you can execute this from the new files path ("C:\Users\Public\modified")
for %%d IN (*.aaxplugin) do (mkdir "%%d_temp/Contents\x64" & move "%%d" "%%d_temp/Contents\x64/%%d" & rename "%%d_temp" "%%d")
with that, I iterate over every plugin and create a folder with the same name (I create _temp because of name colision, after moving the file I rename it to the correct one), also with the subfolder "/Contents/x64", and move the plugin inside. Once donde, you can just take the resulting folders and place them in their correct path.
Hope it works, for me it works like a charm.
I have to run a tool(.exe) that is stored in a particular folder.(Say C:\Temp)
The input parameter for this tool is the (.inf) files placed in various other folders/subfolders.(Say C:\Test\SampleInfFiles, C:\Test\SampleInfFiles\Inf2)
I want to create a batch file where i can run this tool recursively on the various folders.
I am not sure how to provide the folder name of the inf as the input parameter to the tool.
#echo off
for /r /d C:\Test\SampleInfFiles %%x in (dir /b *.inf) do(
pushd "%%x"
call C:\Test\ScanInf.exe
popd
)
I am new to all this. Could you please help create a batch file.
If I understand correctly, you need to specify the folder that contains one or more inf files to the executable, and not the inf files itself.
Apparently the order of parameters is important. for expects the part after /r to be a path. Furthermore, you can just specify * as a set.
The loop now browses all subfolders of the given folder. Inside the loop, it will check if that folder contains an inf file (on that level). If it does, the executable is called with the folder as parameter. Notice the use of ~ in the variable. This strips off any quotes, so you can safely add quotes without risking to have double quotes.
#echo off
for /d /r C:\Test\SampleInfFiles\ %%x in (*) do (
pushd "%%~x"
if exist %%x\*.inf call C:\Test\ScanInf.exe "%%~x"
popd
)
See: Using batch parameters
Here as a nice one-liner:
for /R "C:\Test\SampleInfFiles" /D %%X in (*.*) do if exist "%%~fX\*.inf" call C:\Test\ScanInf.exe "%%~fX"
If you want to run that in the command prompt directly, replace each %% by %.
I think the call command could be omitted.
I need to write/use a batch file that processes some imagery for me.
I have one folder full of nested folders, inside each of these nested folders is one more folder that contains a number of TIF images, the number of images vary in each folder. I also have a batch file, lets call it ProcessImages.bat for Windows that you can "drop" these TIF files on (or obviously specify them in a command line list when invoking the bat); upon which it creates a new folder with all my images process based on an EXE that I have.
The good thing is that because the bat file uses the path from the folders you "drop" onto it, I can select all the TIFs of one folder and drop it to do the processing... but as I continue to manually do this for the 300 or so folders of TIFs I have I find it bogs my system down so unbelievably and if I could only process these one at a time (without manually doing it) it would be wonderful.
All that said... could someone point me in the right direction (for a Windows bat file AMATEUR) in a way I can write a Windows bat script that I can call from inside a directory and have it traverse through ALL the directories contained inside that directory... and run my processing batch file on each set of images one at a time?
You may write a recursive algorithm in Batch that gives you exact control of what you do in every nested subdirectory:
#echo off
call :treeProcess
goto :eof
:treeProcess
rem Do whatever you want here over the files of this subdir, for example:
for %%f in (*.tif) do echo %%f
for /D %%d in (*) do (
cd %%d
call :treeProcess
cd ..
)
exit /b
Aacini's solution works but you can do it in one line:
for /R %%f in (*.tif) do echo "%%f"
Jack's solution work best for me but I need to do it for network UNC path (cifs/smb share) so a slight modification is needed:
for /R "\\mysrv\imgshr\somedir" %%f in (*.tif) do echo "%%f"
The original tip for this method is here
Posting here as it seems to be the most popular question about this case.
Here is an old gem I have finally managed to find back on the internet: sweep.exe. It executes the provided command in current directory and all subdirectories, simple as that.
Let's assume you have some program that process all files in a directory (but the use cases are really much broader than this):
:: For example, a file C:\Commands\processimages.cmd which contains:
FOR %%f IN (*.png) DO whatever
So, you want to run this program in current directory and all subdirectories:
:: Put sweep.exe in your PATH, you'll love it!
C:\ImagesDir> sweep C:\Commands\processimages.cmd
:: And if processimages.cmd is in your PATH too, the command becomes:
C:\ImagesDir> sweep processimages
Pros: You don't have to alter your original program to make it process subdirectories. You have the choice to process the subdirectories only if you want so. And this command is so straightforward and pleasant to use.
Con: Might fail with some commands (containing spaces, quotes, I don't know). See this thread for example.
I know this is not recursion (iteration through enumerated subdirectories?), but it may work better for some applications:
for /F "delims=" %%i in ('dir /ad /on /b /s') do (
pushd %%i
dir | find /i "Directory of"
popd
)
Replace the 3rd line with whatever command you may need.
dir /ad - list only directories
The cool thing is pushd does not need quotes if spaces in path.
rem Replace "baseline" with your directory name
for /R "baseline" %%a in (*) do (
echo %%a
)