Search code examples
batch-fileinkscape

Svg to png many files conversion using Inkscape from batch file


I have a folder containing many svg files and I would like to convert them to png files using inkscape with a batch script (Windows 10 *.bat file). the following script works correctly for a single file but, how to iterate the same command for hundreds of files inside a directory?

PATH = "C:\Program Files\Inkscape"

inkscape myfile.svg --export-png=myfile.png

Solution

  • @echo off
    for %%i in ("%~dp0*.svg") do (
        echo %%i to %%~ni.png
        "C:\Program Files\Inkscape\bin\inkscape.exe" --export-type="png" "%%i"
    )
    

    Additional options for export are listed in this Wiki page, and in the man page (official documentation): in particular, you can set the DPI, height/width, what zone you export, etc.

    To speed things up by utilizing all of your logic cores, you can use this multitasking approach:
    Parallel execution of shell processes

    @echo off
    setlocal enableDelayedExpansion
    
    :: Define the command that will be run to obtain the list of files to process
    set listCmd=dir /b /a-d "%~dp0*.svg"
    
    :: Define the command to run for each file, where "%%F" is an iterated file name from the list
    ::   something like YOUR_COMMAND -in "%%F" -out "%%~nF.ext"
    set runCmd=""C:\Program Files\Inkscape\bin\inkscape.exe" --export-type="png" "%%F""
    
    :: Define the maximum number of parallel processes to run.
    set "maxProc=%NUMBER_OF_PROCESSORS%"
    
    ::---------------------------------------------------------------------------------
    :: The remainder of the code should remain constant
    ::
    
    :: Get a unique base lock name for this particular instantiation.
    :: Incorporate a timestamp from WMIC if possible, but does not fail if
    :: WMIC not available. Also incorporate a random number.
      set "lock="
      for /f "skip=1 delims=-+ " %%T in ('2^>nul wmic os get localdatetime') do (
        set "lock=%%T"
        goto :break
      )
      :break
      set "lock=%temp%\lock%lock%_%random%_"
    
    :: Initialize the counters
      set /a "startCount=0, endCount=0"
    
    :: Clear any existing end flags
      for /l %%N in (1 1 %maxProc%) do set "endProc%%N="
    
    :: Launch the commands in a loop
      set launch=1
      for /f "tokens=* delims=:" %%F in ('%listCmd%') do (
        if !startCount! lss %maxProc% (
          set /a "startCount+=1, nextProc=startCount"
        ) else (
          call :wait
        )
        set cmd!nextProc!=%runCmd%
        echo -------------------------------------------------------------------------------
        echo !time! - proc!nextProc!: starting %runCmd%
        2>nul del %lock%!nextProc!
        %= Redirect the lock handle to the lock file. The CMD process will     =%
        %= maintain an exclusive lock on the lock file until the process ends. =%
        start /b "" cmd /c >"%lock%!nextProc!" 2^>^&1 %runCmd%
      )
      set "launch="
    
    :wait
    :: Wait for procs to finish in a loop
    :: If still launching then return as soon as a proc ends
    :: else wait for all procs to finish
      :: redirect stderr to null to suppress any error message if redirection
      :: within the loop fails.
      for /l %%N in (1 1 %startCount%) do 2>nul (
        %= Redirect an unused file handle to the lock file. If the process is    =%
        %= still running then redirection will fail and the IF body will not run =%
        if not defined endProc%%N if exist "%lock%%%N" 9>>"%lock%%%N" (
          %= Made it inside the IF body so the process must have finished =%
          echo ===============================================================================
          echo !time! - proc%%N: finished !cmd%%N!
          type "%lock%%%N"
          if defined launch (
            set nextProc=%%N
            exit /b
          )
          set /a "endCount+=1, endProc%%N=1"
        )
      )
      if %endCount% lss %startCount% (
        timeout /t 1 /nobreak >nul
        goto :wait
      )
    
    2>nul del %lock%*
    echo ===============================================================================