Skip to content

Instantly share code, notes, and snippets.

@adriansr
Created February 19, 2018 15:21
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save adriansr/1da9b18a8076b0f8a977a5eea0ae41ef to your computer and use it in GitHub Desktop.
Save adriansr/1da9b18a8076b0f8a977a5eea0ae41ef to your computer and use it in GitHub Desktop.
Convert SVG file to macOS icon (icns) format
#!/bin/sh -x
set -e
SIZES="
16,16x16
32,16x16@2x
32,32x32
64,32x32@2x
128,128x128
256,128x128@2x
256,256x256
512,256x256@2x
512,512x512
1024,512x512@2x
"
for SVG in "$@"; do
BASE=$(basename "$SVG" | sed 's/\.[^\.]*$//')
ICONSET="$BASE.iconset"
mkdir -p "$ICONSET"
for PARAMS in $SIZES; do
SIZE=$(echo $PARAMS | cut -d, -f1)
LABEL=$(echo $PARAMS | cut -d, -f2)
svg2png -w $SIZE -h $SIZE -i "$SVG" -o "$ICONSET"/icon_$LABEL.png
done
iconutil -c icns "$ICONSET"
rm -rf "$ICONSET"
done
@abemedia
Copy link

Not sure which version of svg2png was used here but the latest one doesn't have the -i flag. Instead it needs to be an argument i.e.

svg2png "$SVG" -w $SIZE -h $SIZE -o "$ICONSET"/icon_$LABEL.png

@seanr
Copy link

seanr commented Sep 5, 2020

Current version installed via homebrew no longer uses -o either. Both filenames are simple arguments:

svg2png -w $SIZE -h $SIZE "$SVG" "$ICONSET"/icon_$LABEL.png

@bskiefer
Copy link

bskiefer commented Nov 9, 2020

Loop over a directory of SVGs with the fixes mentioned above, while ignoring errors:

#!/bin/sh -x

set -e

SIZES="
16,16x16
32,16x16@2x
32,32x32
64,32x32@2x
128,128x128
256,128x128@2x
256,256x256
512,256x256@2x
512,512x512
1024,512x512@2x
"

FILES=/Zafiro-icons-master/apps/scalable/*
for SVG in $FILES
do
  echo "Processing $f file..."
  # take action on each file. $f store current file name
  BASE=$(basename "$SVG" | sed 's/\.[^\.]*$//')
    ICONSET="$BASE.iconset"
    mkdir -p "/icons/$ICONSET"
    for PARAMS in $SIZES; do
        SIZE=$(echo $PARAMS | cut -d, -f1)
        LABEL=$(echo $PARAMS | cut -d, -f2)
        svg2png -w $SIZE -h $SIZE "$SVG" "/icons/$ICONSET"/icon_$LABEL.png || true
    done

    iconutil -c icns "/icons/$ICONSET" || true
    rm -rf "$ICONSET"
done

@rickerp
Copy link

rickerp commented May 24, 2021

Dependecies? Where do I get svg2png and iconutil?

@seanr
Copy link

seanr commented May 24, 2021

I think I did brew install svg2png or similar. It's been a while but Google should find current answers.

@0x1D-1983
Copy link

Thank you for this! It works as expected and generates icns files with transparent background. 👍🏻

@sdkks
Copy link

sdkks commented Mar 23, 2024

Based on previous contributions, made this shell function which works for me, input is a single file or more. tested with zsh

function svg_to_icns(){
    local RESOLUTIONS=(
        16,16x16
        32,16x16@2x
        32,32x32
        64,32x32@2x
        128,128x128
        256,128x128@2x
        256,256x256
        512,256x256@2x
        512,512x512
        1024,512x512@2x
    )

    for SVG in $@; do
      BASE=$(basename "$SVG" | sed 's/\.[^\.]*$//')
        ICONSET="$BASE.iconset"
        ICONSET_DIR="./icons/$ICONSET"
        mkdir -p "$ICONSET_DIR"
        for RES in ${RESOLUTIONS[@]}; do
            SIZE=$(echo $RES | cut -d, -f1)
            LABEL=$(echo $RES | cut -d, -f2)
            svg2png -w $SIZE -h $SIZE "$SVG" "$ICONSET_DIR"/icon_$LABEL.png
        done

        iconutil -c icns "$ICONSET_DIR"
    done
}

Example usage

$ svg2png -V
0.1.3
$ svg_to_icns notepad.svg
$ file icons/notepad.icns
notepad.icns: Mac OS X icon, 100192 bytes, "ic12" type
image

You can also turn this into a script, add set -e at least for exiting on error, however then the script must be in your path if you want to be able to invoke it from anywhere, or use as an alias with full path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment