Retrieving variable value from filename with a batch file - windows

Is there a way with a batch file to instantly MOVE a file when it's downloaded into Directory A into Directory B based on a variable in the file's name?
I have a file naming convention that looks like this: Photo-87654321-1.jpeg
The 87654321 part is the variable. Now, with if statements and such, I can locate the directory, or if it doesn't exist, create the directory and then place the image in there. The problems I'm having is: a) copying that variable string from the file name, b) running this script every time a file is moved into Directory A.

You haven't given enough details about what you want to do with the file when you find the variable number, so I can only improvise.
This script will get the variable name from the files in C:\DirectoryA and then move them into a folder with that name.
:LOOP
for /f "tokens=2 delims=-" %%a in ('dir /b /a-d "C:\DirectoryA"') do (
md "%%~na"
move "%%a" "%%~na"
)
goto :LOOP
This should give you enough details to tweak to your needs, but if you need anything more specific please provide more details.
Note: Given that you want to move files as soon as they are put in DirectoryA, this is on an infinite loop, so you may want to watch your CPU.

Related

Trying to make a menu in a windows command prompt

I have a batch file that gets run by the user typing:
usercompile filename
usercompile is a batch file that does this:
copy /y %1.txt lib\incoming_file.txt
and then starts the compiler:
compiler.exe
The compiler has the "incoming_file" name hard-coded into linked source (this can't be chaged), so the current method is simply to copy the user file in and rename it to the known name and run the compiler.
I'd like to present the user with a list of files that are generated when a batch file is run, then the batch file would copy the selected file in, rename it (just like is done now).
So it would look like this:
Please choose a file to compile:
1) matthews_build
2) marks_build
3) lukes_build
and then the user would type 1 or 2 or 3 (in this case) and press enter. The batch file would copy that file to the known file name and launch the compiler. The one good thing is that the files that need to be listed all have a unique extension (.jal).
Any ideas?
I changed my approach and consider my previous answer a bad practice: re-listing the files with a second dir command unnecessarily reads the disk again, not to mention the rare but possible case if a file is added/removed between the 2 dir's and makes the whole thing unreliable.
Based on this brilliant solution I did a possible implementation with dynamic array:
#echo off
set /a counter=0
setlocal enabledelayedexpansion
FOR /f "delims=|" %%i IN ('dir /b /on "yourpath*.jal"') DO (
set /a counter+=1
rem echo !counter!^) %%~ni
set FileList[!counter!]=%%~ni & rem This is an array element, a dinamically created variable
)
rem Iterate through variables:
FOR /l %%i IN (1,1,!counter!) DO (
echo %%i^) !FileList[%%i]!
)
set /p option="Choose an option: "
echo !FileList[%option%]!
endlocal
This makes the file list available for any number of following commands.
One possible solution is to list all .jal files and give them an option number, store the result, and based on user input, look up the file based on the option number. As I know no way of storing such a result in memory (no array/hash table data type), only in a file, if a file can not be used, then the listing should be repeated in a deterministic way so that if we re-assign the option numbers, we get the same result. We can do it ensuring alphabetical ordering.
Here is one implementation:
BLOCK 1
setlocal enabledelayedexpansion
FOR /f "delims=|" %%i IN ('dir /b /on "yourpath\*.jal"') DO (
set /a counter+=1
echo !counter!^) %%~ni
)
endlocal
The nested dir command ensures alphabetical ordering (reference.)
A remark why I put a pipe (|) as a delimiter: if you don't define a delimiter, the default space will be used. If your file name contains space then it would be truncated. So I picked a character that is not valid in file names ensuring the whole file name is returned.
Now if you get a number from the user by this:
set /p option=Choose your option:
after this command (evaluating and possibly re-requesting the input) to do a lookup for the file you can repeat BLOCK 1 but replace the echo line with examining the option like this:
if !counter! == %option%
and put those commands in the if block to do whatever you want to do with the file (for debugging, put back the echo command).

Parsing every file in submap recursively to output folder whilst maintaining relativity

I'm using the following batch code to convert all files in a certain directory if the target file doesn't already exist however I'm stuck at getting this to run through every submap and file within that (and keep the output relative with that submap)
So I currently use this:
for %%f in (input/textures/*.*) do ( IF NOT EXIST "ouput/textures/%%~nf.dds" (
"bin/ThempImageParser.exe" "input/textures/%%f" "ouput/textures/%%~nf.dds"
)
)
This works perfectly for a single folder (as was intended), it takes all the files in that specific folder, and passes them as arguments to my executable, which then outputs the file on the path of the second argument.
However this also contains a flaw (this is an additional problem though..) as it does not work if the output -folder- does not exist, so if possible I'd also want it to create the folder if need be.
I've found some batch documentation (I really don't have much experience with Batch) showing me a command called FORFILES and the /R parameter, however I couldn't adjust this so it'd keep the relative paths for the output too, it'd require string manipulation and I have no clue on how to do that.
So the result I'm after is something like this, it takes any file deeper than "input/textures/ for example:
input/textures/some/very/deep/submap/why/does/it/go/on/myfile.anyExtension
it should then take that file (and relative path) and basically change "input" with "output" and replace the file extension with .dds like this:
ouput/textures/some/very/deep/submap/why/does/it/go/on/myfile.dds
and pass those two strings to my executable.
#ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir\t w o"
SET "destdir=U:\destdir\wherever\something"
FOR /f "delims=" %%a IN ('xcopy /y /L /s "%sourcedir%\*"') DO (
SET "destfile=%%a"
SET "destfile=!destfile:*%sourcedir%=%destdir%!"
IF /i "%%a" neq "!destfile!" (
FOR %%m IN ("!destfile!") DO IF NOT EXIST "%%~dpm%%~na.dds" (
ECHO MD "%%~dpm"
ECHO "bin\ThempImageParser.exe" "%%a" "%%~dpm%%~na.dds"
)
)
)
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
First, perform an xcopy with the /L option to list-only the individual fullnames of files that would be copied by the xcopy.
Assign each name found from %%a to destfile, then remove all characters before the source-directoryname from that filename, and replace that string with the destination directoryname.
This will yield the destination name for the file (with the original extension). The only exception will be the very last output line, which is a count-of-files report. Since this line will not contain the source directoryname, the replacement will not take place, so %%a will be the same as !destfile! - so we eliminate that.
Now assign the destination filename to a metavariable so we can select its various parts, and if the filename made from the destination drive and pathname, the name part of the original file and .dds does not exist, then make the destination directoryname and execute the imageparser, providing the desired output filename.
Note that these last two are ECHOed instead of being executed for testing purposes. Remove the ECHOes to actually perform the command.
Note that / is a switch-indicator, \ is a directory-separator.
Note that MD will report an error if the directory already exists. Append 2>nul to the end of the md command to suppress that error message.

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.

Bulk renaming files in relation to the folder names

I am very new to coding and bulk processes but i am looking for a command line SPECIFICALLY for windows command prompt and i am wondering if such a thing exists. So I have a folder containing 111 subfolders, with each subfolder containing between 20 and 40 png image files. Each subfolder is named 001-111 accordingly and the png files are ordered how i want them, however i am looking for a command line that would be able to quickly and efficiently name all the pngs in the folders to the name of the folder followed by the png number in brackets
e.g. for folder 037, i would want the png's to be renamed to: 037(1), 037(2), 037(3) etc...
I am hoping for the best although i am unsure such a code may not be possible or be simply done.
Also if you come up with a code that achieves this process, it would be great if you could reply with the simple command line that i could use rather than a full explanation because i am new to coding and far from fluent with the language or terms or how things work. I know this same process can be achieved by going select all>rename (ctrl a>f2) and renaming to the folder name however i need to use this process frequently and dont want to have to open each folder, i would rather have a command line for cmd that would do it swiftly
Thank you and a simple answer would be greatly appreciated
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "parentdir=u:\parent"
FOR /l %%a IN (1001,1,1111) DO (
SET dir=%%a&SET "dir=!dir:~1!"
FOR /f "delims=" %%i IN ('dir /a-d /b "%parentdir%\!dir!\*.png" 2^>nul') DO (
ECHO REN "%parentdir%\!dir!\%%~nxi" "!dir!(%%~ni)%%~xi"
)
)
GOTO :EOF
Test results:
Starting directory :
u:\parent\001\1.png
u:\parent\037\1.png
u:\parent\037\2.png
u:\parent\111\999 with spaces in name.png
Script response
REN "u:\parent\001\1.png" "001(1).png"
REN "u:\parent\037\1.png" "037(1).png"
REN "u:\parent\037\2.png" "037(2).png"
REN "u:\parent\111\999 with spaces in name.png" "111(999 with spaces in name).png"
Obviously, you'd need to replace the value assigned to parentdir with your actual target directory name.
The script will report the renames it proposes to do. To actually invoke the rename remove the ECHO keyword.
I would create a batch file like so:
renamepng.bat:
cd %%1
if ERRORLEVEL 1 goto end
for %f in *.png do mv "%f" "%%1(%f).png"
cd ..
:end
This will attempt to cd to the directory name provided on the command line, abort if that fails, then rename all the .png files and return to the previous directory
then call it like so:
for %d in ??? do call renamepng.bat %d
which will loop through all 3-character file and directory names in the current directory, can call the batch file on each one. Using call instead of just the batch file name causes execution to return to the loop when the batch finishes.

Batch File to Delete Files in Folders

I have many folders in a directory that contain various files. Each filename begins with XXX_ where XXX could be the name of the folder the file is in. What I am needing to do is to go through all those folders and delete any file where XXX is the name of the folder that file is in.
Please have an eye out this question: Iterating through folders and files in batch file?.
I think this should help you.
Please let me know if you need further assistance.
EDIT #1
The joker character in DOS command line is *. Then, while searching a directory for certain files, you may consider your regular expression, that is, your XXX_, and complete it with *, this shall return only the files for which you're looking for.
This means that instead of *.zip pattern in one of the FOR loops given the linked question, your first FOR loop should contain your directory name, then take this variable concatenated with the * character to obtain only the files you're looking for.
For example, consider trying the following:
dir /s XXX_*.*
This should return only the files you're interested in, given the right folder name.
EDIT #2
Thanks for having precised your concern.
Here is a code sample that, I do hope so, should help. Now I know you say you have the looping correct, so that perhaps only piece of this code might be needed.
#echo off
setlocal enableextensions enabledelayedexpansion
for /F "delims==" %%d in ('dir /ogne /ad /b /s .') do (
for /F "delims==" %%f in ('dir /b "%%d\%%~nd_*.*"') do (
echo %%d\%%f
)
)
endlocal
This works and lists the files contained in subfolders from the current (.) folder.
I have tested it from the following folder:
C:\Docume~1\marw1\MyDocu~1\MyMusi~1
Where a 'XXX' folder is contained. This 'XXX' folder contains the following files:
Copy of XXX_blah.bmp;
XXX_blah.bmp;
XXX_1234.ppt;
XXX_textfile.txt.
From this structure, the output is:
C:\Docume~1\marw1\MyDocu~1\MyMusi~1\XXX\XXX_blah.bmp
C:\Docume~1\marw1\MyDocu~1\MyMusi~1\XXX\XXX_1234.ppt
C:\Docume~1\marw1\MyDocu~1\MyMusi~1\XXX\XXX_textfile.txt
I then suspect that putting a del instruction instead of an echo command shall do the trick. This means that to isolate the foldername itself from its path, you need to use the ~n instruction with your folder variable name like %%~nd, where your iterating folder variable name is %%d.
Furthermore, you could even use a parameterized batch file in the process, instead of hardcoding it, that is, if your 'set YourFolder =...' is part of your production code. This could look like:
#echo off
setlocal...
set root = %1
set root = %root:~1%
set root = %root:~0,-1%
...
endlocal
Instead of having '.' as pictured in my first FOR loop, your would replace it with "%root%" in order to consider your command line parameter instead of a hardcoded filepath.
I do help this helps, sincerely!
As Ron says, since the question is tagged "windows".
EDIT:
Ron's answer, which seems to have disappeared!, was to use del /s
EDIT2:
OK, it's valid only for file names, not for directories. For the directories you'd have to use something like sketched below.
Additional info: when you want to do the same thing recursively to files in a directory tree, and (unlike del) there's no command that already does the traversing for you, you can use the /R option of the for command.
To see the for command's docs, do e.g. start "for-help" cmd /k for /?.
Cheers & hth.,
– Alf
cd C:\"foldername"
del /s XXX_"*"
cls
exit

Resources