Batch perform action on all files in dir - wrong variable value? - windows

I'm trying to convert a folder of SWFs to images using swftools.
The actual conversion is working fine, however I'm having issues trying to get it to run for all files in a folder. (and would be nice to get it to work for all subfolders as well).
Let's say the folder contains the following files: 1.swf, 2.swf, ...
Now the script I wrote for this is:
for %i in (*.swf) do (
set fileName=%i
swfrender "%fileName%" -o "%fileName:~0,-4%.png"
)
Which I'm running from inside the folder containing the SWF files. However rather than the expected result I'm seeing the following in my command prompt:
set fileName=1.swf swfrender "3.swf" -o "3.png" )
set fileName=2.swf swfrender "3.swf" -o "3.png" )
Now from what I could find the script should be fine, so I have no clue what's going wrong.
Oddly enough the following does seem to work:
for /R %x in (*.swf) do swfrender %x -o %x.png
But I'd rather not have to rename a couple of hundred files to remove the redundant .swf portion from the filename.

you need delayed expansion (and in batch files you need doubled % for the loops tokens):
setlocal enableDelayedExpansion
for %%i in (*.swf) do (
set fileName=%%i
swfrender "!fileName!" -o "!fileName:~0,-4!.png"
)
or you can extract the file name without extension:
for %%i in (*.swf) do (
swfrender "%%~i" -o "%%~ni.png"
)

Related

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

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"

Problem with EnableDelayedExpansion, For, and filenames with special characters like ! % &

The Setup:
I have a set of files of type .type1 and want to batch convert them to .type2 using a program I have
The converting program Program.exe (in a folder called TOOLS) takes two arguments -i for InputFile and -o for OutputFile but is unable to create folders/directories (if the output folder doesn't exist it fails)
The .type1 files are in different folders. All of these folders are in a folder called InputFolder
I want the .type2 converted files to be outputted to the OutputFolder preserving the folder structure of the originals
So, In the main folder I have 4 things:-
A. InputFolder :where all the input files (divided into different folders) exist
B. OutputFolder:where all the converted files should be outputted (divided into different folders matching the InputFolder)
C. TOOLS :where the converter Program.exe exists
D. Batch Convert.bat :the batch file I wrote to batch convert the files. The contents of which are in the next section
What I tried:
rem -------Setting some general variables-------
set "BatchPath=%~dp0"
set "InputPath=%BatchPath%InputFolder\"
set "OutputPath=%BatchPath%OutputFolder\"
rem -------Saving a list of all .type1 files-------
dir /s/b/a-d "%InputPath%*.type1">"%BatchPath%TOOLS\FilesList.txt"
rem -------Starting a loop for each file listed in FilesList.txt -------
for /f "usebackq delims=" %%j in ("%BatchPath%TOOLS\FilesList.txt") do (
setlocal EnableDelayedExpansion
rem --Setting variables replacing "input string" with "output string"--
set "InputFileType2=%%~dpnj.type2"
set "OutputFile=!InputFileType2:%InputPath%=%OutputPath%!"
set "InputFilePath=%%~dpj"
set "OutputFilePath=!InputFilePath:%InputPath%=%OutputPath%!"
rem --Creating output folders--
mkdir "!OutputFilePath!"
rem --Start the converting process--
"%BatchPath%TOOLS\Program.exe" -i "%%j" -o "!OutputFile!"
endlocal
)
The Problem:
Some of the folders and the files inside the InputFolder have special characters (like ! % &) which cause problems with the converting.
Is there a way to do this with the least amount of conflict with special characters (like removing the need to EnableDelayedExpansion to remove conflict with !?
is there a way to do it without the PwerShell or the Call function?
(because I have thousands of big files and the Call function can be slow and it seems like it always tries to access the HDD first before a :Label)
As compo said, you just need to change the order of lines.
It's important to expand the FOR variables only with delayed expansion disabled.
Because expanding them inside delayed expansion enabled, destroys the exclamation marks !
for /f "usebackq delims=" %%j in ("%BatchPath%TOOLS\FilesList.txt") do (
rem --Setting variables replacing "input string" with "output string"--
set "InputFileType2=%%~dpnj.type2"
set "OutputFile=!InputFileType2:%InputPath%=%OutputPath%!"
set "InputFilePath=%%~dpj"
set "helper=%%j"
setlocal EnableDelayedExpansion
set "OutputFilePath=!InputFilePath:%InputPath%=%OutputPath%!"
rem --Creating output folders--
mkdir "!OutputFilePath!"
rem --Start the converting process--
"%BatchPath%TOOLS\Program.exe" -i "!helper!" -o "!OutputFile!"
endlocal
)

Batch ps2pdf fails

I still have not solved why this code which correctly runs through all the sub folders, looking for jpg files to convert to pdf files and compresses them but exits before executing any command after the final ')'. It is definitely due to ps2pdf but can't think of what ps2pdf can be changing. Any ideas?
#echo on
set records="C:\Users\john\Documents\0 BDHS Digitised records\Awaiting processing\"
cd %records%
setlocal enabledelayedexpansion
for /r . %%G in (.) do ( Pushd %%G
If %errorlevel% NEQ 0 goto:eof
rem merge jpgs to PDF
jpeg2pdf.exe *.jpg -o "%%~nG".pdf
set fname=%%G
ps2pdf -dPDFSETTINGS#/ebook "%%~nG".pdf "%%~nG"compressed.pdf
popd )
echo Ended
pause
Here is an example of your script, with the required Call for your ps2pdf.bat file.
Before running it, please substitute the correct full paths for your executable utility, jpeg2pdf.exe, (line 14), and script ps2pdf.bat, (line 15). It is not a good idea to rely on modifiable registry or environment variables hence the reason I'm advising their full paths. If those two files will always be located in the directory of this batch file, or relative to it, feel free to use %~dp0 in designating those paths.
#Echo Off
SetLocal DisableDelayedExpansion
Set "records=%UserProfile%\Documents\0 BDHS Digitised records\Awaiting processing"
Set "fname="
If Exist "%records%\" (
For /R "%records%" %%G In (*.jpg) Do (
SetLocal EnableDelayedExpansion
If Not "!fname!" == "%%~dpG" (
EndLocal
Set "fname=%%~dpG"
For %%H In ("%%~dpG.") Do (
Rem Merge JPGs to PDF
"P:\athTo\EXE\jpeg2pdf.exe" "%%~dpG*.jpg" -o "%%~dpG%%~nxH.pdf"
Call "P:\athTo\ps2pdf.bat" -dPDFSETTINGS#/ebook "%%~dpG%%~nxH.pdf" "%%~dpG%%~nxHcompressed.pdf"
)
) Else EndLocal
)
Echo Ended.
) Else Echo Directory %records% dos not exist.
Pause
The example above, has been made more efficient, by only recursing through directories which contain files with .jpg extensions.
The script however does not step in an out of directories using PushD and PopD, as did yours. Whilst this may be a slight improvement efficiency wise, it may bring rise to another issue. As I do not know your utilities, if they only accept limited length commandlines or paths, this version could choke.

Bat script to find and replace files in multiple subfolders - replace .java files with .class files from specific folder

I am new to windows batch scripting .. please help on this scenario
I have file structures as below ::
dir1:
c:\workspace\changeset\com\folder
subfolder1
one.java
subfolder-2
two.java
dir2:
c:\workspace\target\class\com\folder
subfolder1
one.class
subfolder2
two.class
Subfolder3
three.class
Need to find and replace dir1 files in respective subfolders i.e one.java and two.java from dir2 files i.e one.class and two.class ( need to replace certain .java files with .class files from specific folder )
much appreciated for your help.
Thanks
Arjun
for /f "delims=" %%a in ('dir /b /a-d "c:\workspace\changeset\com\folder\*.java"') do (
if exist "c:\workspace\target\class\com\folder\%%~na.class" (
echo copy "c:\workspace\target\class\com\folder\%%~na.class" "c:\workspace\changeset\com\folder\%%a")
)
The required COPY commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO COPY to COPY to actually copy the files. Append >nul to suppress report messages (eg. 1 file copied)
Note that execution directly from the prompt and as lines with a batch file are different. The metavariable (loop-control variable) %%x must be referenced as %%x for a batch line and %x if executed from the command prompt. Since it makes little sense to repeatedly execute a line containing a for from the prompt (it's easier to create a batch file), I post the batch-file version. User's responsibility to adjust for direct-from-prompt if desired.
Read each filename in /b basic form /a-d without directories and assign the filename+extension to %%a.
If a file in the other directory called thenamepartofthefile.class exists, then copy that file to the first directory.
Please post the entire problem to be solved. The approach can change radically, as in this case.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir1=U:\sourcedir\changeset"
SET "sourcedir2=U:\sourcedir\target"
FOR /f "delims=" %%a IN (
'dir /b /s /a-d "%sourcedir1%\*.java" '
) DO (
SET "javadir=%%~dpa"
SET "classfile=!javadir:%sourcedir1%=%sourcedir2%!%%~na.class"
IF EXIST !classfile! ECHO COPY "!classfile!" "%%a"
)
GOTO :EOF
You would need to change the settings of sourcedir1 and sourcedir2 to suit your circumstances.
Essentially, the same approach and the same comments re messages. The difference is that this procedure uses files and subdirectories in the dir list and substitutes the first part of the directoryname in deriving the expected name of the .class file.

For loop in batch file reading a file of File Paths

I want to write a Windows batch file script that will loop through a text file of FILE PATHS, do some work using data from each file path, then ultimately delete the file.
I started by running the FORFILES command and sending its output (the #PATH parameter is the full path of any file it matches) to a text file (results.txt).
I end up with a results.txt file like this:
"C:/Windows/Dir1/fileA.log"
"C:/Windows/Dir1/fileA.log"
"C:/Windows/Dir2/fileC.log"
"C:/Windows/Dir3/fileB.log"
What I want to do is:
Use a FOR loop and read each line in the results.txt file
For each line (file path), strip out the directory name that the log file is sitting in (ie: Dir1, Dir2, etc..) and create a directory with that SAME name in a different location (ie. D:/Archive/Backups/Dir1, D:/Archive/Backups/Dir2, etc..) -- assuming the directory doesn't exist.
Move the actual .log file to a zip file in that directory [I have code to do this].
Delete the .log file from its original location. [Pretty straightforward]
I'm having trouble figuring out the best way to accomplish the first 2 steps. My FOR loop seems to stop after reading the very first line:
FOR /F "tokens=1,2,3,4,5,6,7,8,9,10 delims=\" %%G in ("results.txt") DO (
...
)
You don't want to parse the path with the tokens/delims options because you don't know how many directory levels you are dealing with. You want to preserve each line in its entirety. TO parse the path you want to use the FOR variable modifiers. (type HELP FOR from the command line and look at the last section of the output)
%%~pG gives the path (without the drive or file name). If we then strip off the last \, we can go through another FOR iteration and get the name (and possible extension) of the file's directory by using %%~nxA.
The toggling of delayed expansion is just to protect against a possible ! in the path. If you know that no path contains ! then you can simply enable delayed expansion at the top of the script and be done with it.
EDIT - this code has been modified significantly since Aacini pointed out that I misread the requirements. It should satisfy the requirements now.
for /f "usebackq delims=" %%G in ("results.txt") do (
set "myPath=%~pG"
setlocal enableDelayedExpansion
for /f "eol=: delims=" %%A in ("!myPath:~0,-1!") do (
endlocal
if not exist d:\Archive\Backups\%%~nxA md d:\Archive\Backups\%%~nxA
rem ::zip %%G into zip file in the D: location
rem ::you should be able to create the zip with the move option
rem ::so you don't have to del the file
)
)
I wrote this to timestamp files before offloading to SFTP.
Hope you find it useful.
The timestamp coding may seem irrelevant to your issue, but I left it because it's a good example of dissecting the filename itself.
I suggest you put an ECHO in front of the REN command for testing. Different shells may have different results.
In the end, the delayedexpansion command wasn't necessary. It was the sub-routine that fixed my issues with variables inside the loop. That could possibly be because of my OS ver. (Win 8.1) - It wouldn't hurt to leave it.
#echo off
cls
setlocal enabledelayedexpansion
if %time:~0,2% geq 10 set TIMESTAMP=%date:~10,4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%
if %time:~0,2% leq 9 set TIMESTAMP=%date:~10,4%%date:~4,2%%date:~7,2%_0%time:~1,1%%time:~3,2%%time:~6,2%
echo TimeStamp=%TIMESTAMP%
echo.
for %%G in (*.txt) do (
set OLDNAME=%%G
call :MXYZPTLK
)
dir *.txt
goto :EOF
:MXYZPTLK
echo OldName=%OLDNAME%
ren %OLDNAME% %OLDNAME:~0,-4%_%TIMESTAMP%%OLDNAME:~-4,4%
echo.
:END
You have two minor problems:
The path separator in the file is '/' but you use '\' in the for loop.
The quotes around "results.txt" stop it working.
This works. Don't write quotes to results.txt and you won't get a quote at the end of the filename.
#echo off
FOR /F "tokens=3,4 delims=/" %%I in (results.txt) DO (
REM Directory
echo %%I
REM File
echo %%J
)

Resources