Is it possible to use wildcards within a Batch script to grab all directories under a path, and then use the relevant name for the creation of a file - windows

It's a bit of a convoluted title and I apologise for my poor English, it's not my first language and I'm far from fluent. I hope my current code explains my goal better than my written explanation.
#echo off
Setlocal enableextensions enabledelayedexpansion
set BCAT_PATH="C:\\Users\\USER\\Downloads\\FMOD conversion to packable\\0Tools\\bincat"
CD "9temp\\zzz_FSBS_Extract_test"
for /D %%D in (\*) do
"%BCAT_PATH%\\bincat" "%%D\*.ogg" -o "..\\zzz_BuiltOGG_test%%\~ni.tmp"
PAUSE

#echo off
Setlocal enableextensions enabledelayedexpansion
set "BCAT_PATH=C:\Users\USER\Downloads\FMOD conversion to packable\0Tools\bincat"
CD "9temp\zzz_FSBS_Extract_test"
for /D %%D in (*) do FOR %%i in ("%%D\*.ogg") do ECHO "%BCAT_PATH%\bincat" "%%i" -o "..\zzz_BuiltOGG_test\%%~ni.tmp"
PAUSE
Use set "var1=data" for setting string values - this avoids problems caused by trailing spaces. In comparisons; don't assign a terminal \, space or quotes - build pathnames from the elements - counterintuitively, it is likely to make the process easier.
Your CD statement will change to a directory RELATIVE to your current directory, so if you are currently at C:\somewhere to C:\somewhere\9temp\zzz_FSBS_Extract_test. If 9temp\zzz_FSBS_Extract_test is an absolute location, then you'd need \9temp\zzz_FSBS_Extract_test
for /D %%D in (\*) do would set %%D to each directoryname in the root directory. Since you've changed to ..?..9temp\zzz_FSBS_Extract_test, you need * to scan the current directory. You could also use "..?..9temp\zzz_FSBS_Extract_test\*" without changing directory. *I don't know where 9temp\... is, so I've used ..?.. to represent its location.
Note that the command to be executed must follow directly after the do, on the same physical line. I've added ECHO to show the command that would be executed. After you've verified that the command is correct, remove the echo keyword to actually execute the command.
Note that BCAT_PATH is set to C:\Users\USER\Downloads\FMOD conversion to packable\0Tools\bincat The command generated will thus be "C:\Users\USER\Downloads\FMOD conversion to packable\0Tools\bincat\bincat".
I've no idea where %%i is defined in your program. I've inserted it where I believe it should go. That should set %%i to each .ogg filename in the directory %%D in turn. %%~ni should return the name part of that file.
Your output directory would be ..?..9temp\zzz_BuiltOGG_test since your current directory is ..?..9temp\zzz_FSBS_Extract_test . The \ should be placed between the directoryname and the filename.

There is not need for delayedexpansion although setlocal is a good idea.
This will not do for each directory, but instead find each .ogg file recursively, then run the command on each file. Also note, I've added the .exe extension to bincat
#echo off
setlocal & set "BCAT_PATH=C:\Users\USER\Downloads\FMOD conversion to packable\\0Tools\bincat"
cd /d "9temp\\zzz_FSBS_Extract_test"
for /R %%i in (*.ogg) do "%BCAT_PATH%\bincat.exe" "%%~i" -o "..\zzz_BuiltOGG_test\%%~ni.tmp"

Related

Windows command FOR in batch file, specified to work in a certain folder

Normally I can specify a folder for a batch file to work in.
Not so with the FOR command:
for %%a in (G_*.txt) do ren "%%a" "test-%%a"
This finds G_*.txt in all files and renames those by putting test- in front of the filename.
I tried specifying G_*.txt further with C:\test\G_*.txt but that is not accepted.
I also tried pouring this into a variable but that also failed.
Who knows what to do?
Again, I had to change the approach: using SET /R will put a long path into the %%a variable which makes the idea unsuited to put a bit of text in front of a filename.
I found the solution by selecting the work directory first and let the FOR construction do its work. Since it must be network proof, I had to use the PUSHD command.
This is what the final result looks like:
set source=\\nassie\home\test\source with nasty space
set target=D:\target
PUSHD %source%
:: If this fails then exit
If %errorlevel% NEQ 0 goto:eof
for %%a in (G_*.txt) do xcopy "%source%\%%a" "%target%\textblabla_%%a*" /D /Y
POPD

A bat file to recursively traverse and find certain file type

I am trying to recursively traverse through a directory and find exe files in it.
This is the folder structure
C:\MyCave\iso\SDG\cmpdir
---------------\FolderA
------------------abc.txt
---------------\FolderB
------------------def.exe
---------------\FolderC
------------------ghi.dll
The below is my bat sinppet.
set f="C:\MyCave\iso\SDG\cmpdir\test-recur"
for /r %%f in ("*.exe") do if exist %%f echo %%f
Though it is working and listing out exe files in C:\MyCave\iso\SDG\cmpdir, but I want to list exe files present only in C:\MyCave\iso\SDG\cmpdir\test-recur directory.
This is my current output.
C:\MyCave\iso\SDG\cmpdir>exeRecur.bat
C:\MyCave\iso\SDG\cmpdir>set f="C:\MyCave\iso\SDG\cmpdir\test-recur"
C:\MyCave\iso\SDG\cmpdir>for /R %f in ("*.exe") do if exist %f echo %f
C:\MyCave\iso\SDG\cmpdir>if exist C:\MyCave\iso\SDG\cmpdir\cp.exe echo C:\MyCave\iso\SDG\cmpdir\cp.exe
C:\MyCave\iso\SDG\cmpdir\cp.exe
C:\MyCave\iso\SDG\cmpdir>if exist C:\MyCave\iso\SDG\cmpdir\dirB\Abcd.exe echo C:\MyCave\iso\SDG\cmpdir\dirB\Abcd.exe
C:\MyCave\iso\SDG\cmpdir\dirB\Abcd.exe
C:\MyCave\iso\SDG\cmpdir>if exist C:\MyCave\iso\SDG\cmpdir\test-recur\2\def.exe echo C:\MyCave\iso\SDG\cmpdir\test-recur\2\def.exe
C:\MyCave\iso\SDG\cmpdir\test-recur\2\def.exe
C:\MyCave\iso\SDG\cmpdir>if exist C:\MyCave\iso\SDG\cmpdir\wspace\defg.exe echo C:\MyCave\iso\SDG\cmpdir\wspace\defg.exe
C:\MyCave\iso\SDG\cmpdir\wspace\defg.exe
I know there is a small mistake somewhere. Requesting your help in solving it.
Based on Gerhard's and sst's answer I have modified my script like this.
set rootFolder=%1
set destFolder=%2
for /r %rootFolder% %%f in ("*.exe") do if exist %%f move %%f %destFolder%
I am passing command line arguments to bat like this...
exeRecur.bat "C:\MyCave\iso\SDG\cmpdir\test-recur" "C:\MyCave\iso\SDG\cmpdir\dirA"
Like this hard-coding of paths is avoided.
Regards
Ok, so you are setting a variable:
set f="C:\MyCave\iso\SDG\cmpdir\test-recur"
Firstly, it is bad practice to set single char variables, but more importantly is the way you wrap it with double quotes. It should be from the beginning of the variable to the end of the value.
set "f=C:\MyCave\iso\SDG\cmpdir\test-recur"
The real problem though is that you never tell the for /r loop where to recursively do the search.
set "mypath=C:\MyCave\iso\SDG\cmpdir\test-recur"
for /r "%mypath%" %%f in (*.exe) do echo %%~f
You forgot to specify the 'root path' argument of FOR /R, So it begins the enumeration from the current directory.
You should use a different name for your environment variable to avoid confusion with the FOR's parameter %%f.
set "RootFolder=C:\MyCave\iso\SDG\cmpdir\test-recur"
for /r "%RootFolder%" %%f in (*.exe) do echo %%f
You should also use the extended syntax of the set command: set "var=value" and use "%var%" wherever quoting is needed.
Since you are using the wildcard *.exe, There is no need for if exist in FOR /R as it will only enumerate the existing files.

How do I get a relative path out of a windows batch file using echo?

How do I get relative directories / partial paths to display as echo output from a windows .bat file?
How to split the filename from a full path in batch?
Talks about everything but.
I've found drive letters, filenames, extensions, shortened (8.3) names, and full paths - but no relative paths.
I'm running a recursive FOR /R loop; which traverses sub-directories. I would like something - that doesn't have twenty characters of useless path info - that tells me which directory each duplicate file lives in... without hardcoding the .bat file to live in a certain directory/path?
Maybe a solution would be to measure the length of the script's path and cut that off of the front of the full path? But I don't know how to manipulate that.
Script could be in many locations:
F:\a.bat<BR>
F:\Dir1\fileA.txt<BR>
F:\Dir20\fileA.txt
C:\Users\Longusername\Desktop\Container\a.bat<BR>
C:\Users\Longusername\Desktop\Container\Dir1\fileA<BR>
C:\Users\Longusername\Desktop\Container\Dir20\fileA
And right now the only options I have for output are (%%~nxG):
fileA.txt
fileA.txt
Which doesn't tell me which directory each file is in...or (%%~pnxG)
\Users\Longusername\Desktop\Container\Dir1\fileA.txt
\Users\Longusername\Desktop\Container\Dir20\fileA.txt
What I'd like, from any location:
\Dir1\fileA.txt
\Dir20\fileA.txt
Could be missing the leading \, but that's negligible. Other options than echo are permissible if they'll work on most window machines. They may lead to more questions, though - as I've figured out my other pieces with echo.
quite easy, if you think about it: just remove the current directory path (%cd%):
#echo off
setlocal enabledelayedexpansion
for /r %%a in (*.txt) do (
set "x=%%a"
echo with \: !x:%cd%\=\!
echo without \: !x:%cd%\=!
)
By the way: \folder\file always refers to the root of the drive (x:\folder\file), so it's not exactly a relative path.
This is similar to the already accepted answer, but with delayed expansion enabled only where needed. This should correctly output filenames containing ! characters.
#Echo Off
SetLocal DisableDelayedExpansion
Set "TopLevel=C:\Users\LongUserName"
For /R "%TopLevel%" %%A In ("*.txt") Do (
Set "_=%%A"
SetLocal EnableDelayedExpansion
Echo=!_:*%TopLevel%=!
EndLocal
)
Pause
You could also use Set "TopLevel=%~dp0", (the running script's directory) or Set "TopLevel=%~dp0..", (the running script's parent directory)
One potential benefit of the above method is that you can also use a location relative to the current directory for the value of %TopLevel% too, (in this case, based upon the initial example, the current directory would be C:\Users):
Set "TopLevel=LongUserName"
Although this would only work correctly if LongUserName didn't already exist as content of the path earlier in the tree.
You could use xcopy together with its /S (include sub-directories) and /L (list but do not copy) options since it returns relative paths then, so you do not have to do any string manipulation, which might sometimes be a bit dangerous, particularly when the current directory is the root of a drive:
xcopy /L /S /I /Y /R ".\*.txt" "\" | find ".\"
The appended find command constitutes a filter that removes the summary line # File(s) from the output.
To capture the output of the aforementioned command line just use a for /F loop:
for /F "delims=" %%I in ('
xcopy /L /S /I /Y /R ".\*.txt" "\" ^| find ".\"
') do (
rem // Do something with each item:
echo/%%I
)

remove the directory from output in batchfile

I have the below batchfile that output ReadFile.txt file
cd /d "T:\EMP\SST"
for /r %%i in (T:\EMP\SST) do echo %%i >>D:\MultiThreading\ReadFile.txt
pause
this ReadFile.txt file output
T:\EMP\SST\T:\EMP\SST
T:\EMP\SST\file 11\T:\EMP\SST
T:\EMP\SST\file 12\T:\EMP\SST
T:\EMP\SST\file 13\T:\EMP\SST
I want to remove the directory ouptput T:\EMP\SST so I want my output to be like this
file 11
file 12
file 13
how to do this
I believe you actually need for /D rather than for /R for your task (because I assume file 11, file 12, file 13 are actually directories as they are enumerated by for /R):
for /D %%I in (T:\EMP\SST\*) do echo %%~nxI
Anyway, your for /R syntax is wrong; the directory you want to enumerate recursively needs to be stated immediately after the /R switch (if you omit it, the current directory is assumed), and you need to provide a set (that is the part in between parentheses) that constitutes a pure file name pattern only, without any (absolute or relative) paths, like *.*, for example, to match all files.
In your code, for /R enumerates the current directory. Since your set is T:\EMP\SST and contains no wildcards (*, ?), it is just appended to the enumerated directories literally, because for accesses the file system only in case wildcards are encountered. That explains your weird output.
you're using FOR in a wrong way. The pattern between the parentheses isn't the start directory, it is the file/directory pattern you want to match. Here I suppose you want *.*
If you only want the filenames (no paths at all) you can write:
#echo off
for /r T:\EMP\SST %%i in (*.*) do echo %%~nxi>>D:\MultiThreading\ReadFile.txt
If you want the filenames + relative paths, it's slightly more complicated but doable, by enabling delayed expansion to be able to remove the path prefix + backslash:
#echo off
setlocal enabledelayedexpansion
set start_path=T:\EMP\SST
for /r %start_path% %%i in (*.*) do (
set f=%%i
echo !f:%start_path%\=!>>D:\MultiThreading\ReadFile.txt
)
This FOR command is cryptic and I have to read the help (FOR /?) everytime, but the fact is: everything useful is in there so I do it all the time :)

How to execute an application existing in each specific folder of a directory tree on a file in same folder?

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.

Resources