How to manually create icns files using iconutil? - xcode

When I'm validating my app I get this error:
the application bundle does not contain an icon in ICNS format, containing both a 512x512 and a 512x512#2x image.
I use to make the icns icons with Img2icns app and until today it always worked properly. But now I'm getting that error and there's no way to make it work. I tried to put two PNG files together (512x512 and 1024x1024) in Img2icns but I always get that error. I also tried to follow the instructions in Apple's OS X Human Interface Guideline but when I try to make the icon sets I get this terminal error:
-bash: syntax error near unexpected token 'newline'
I am not very good with terminal commands so maybe I'm doing something wrong. I wrote:
iconutil -c icns </Users/myname/SDK Mac Apps/MyApp/grafica/icon.iconset>
If anyone could help it would be very much appreciated. Thanks, Massy.

Here's a script to convert a 1024x1024 png (named "Icon1024.png") to the required icns file. Save it to a file called "CreateICNS.src" in the folder where your png file is then in terminal "cd" to the same folder and type "source CreateICNS.src" to call it:
mkdir MyIcon.iconset
sips -z 16 16 Icon1024.png --out MyIcon.iconset/icon_16x16.png
sips -z 32 32 Icon1024.png --out MyIcon.iconset/icon_16x16#2x.png
sips -z 32 32 Icon1024.png --out MyIcon.iconset/icon_32x32.png
sips -z 64 64 Icon1024.png --out MyIcon.iconset/icon_32x32#2x.png
sips -z 128 128 Icon1024.png --out MyIcon.iconset/icon_128x128.png
sips -z 256 256 Icon1024.png --out MyIcon.iconset/icon_128x128#2x.png
sips -z 256 256 Icon1024.png --out MyIcon.iconset/icon_256x256.png
sips -z 512 512 Icon1024.png --out MyIcon.iconset/icon_256x256#2x.png
sips -z 512 512 Icon1024.png --out MyIcon.iconset/icon_512x512.png
cp Icon1024.png MyIcon.iconset/icon_512x512#2x.png
iconutil -c icns MyIcon.iconset
rm -R MyIcon.iconset

Checkout the following instructions (link):
Use iconutil to Create an icns File Manually
The iconutil command-line tool converts iconset folders to deployment-ready, high-resolution icns files. (You can find complete documentation for this tool by entering man iconutil in Terminal.) Using this tool also compresses the resulting icns file, so there is no need for you to perform additional compression.
To convert a set of icons to an icns file
Enter this command into the Terminal window:
iconutil -c icns <iconset filename>
where <iconset filename> is the path to the folder containing the set of icons you want to convert to icns. The output is written to the same location as the iconset file, unless you specify an output file as shown:
iconutil -c icns -o <icon filename> <iconset filename>
In other words, you need to replace <iconset filename> by the path:
/Users/myname/SDK Mac Apps/MyApp/grafica/icon.iconset
Since the path contains spaces, you need to use double quotes, for example:
iconutil -c icns "/Users/myname/SDK Mac Apps/MyApp/grafica/icon.iconset"
This command should work properly.

While using all kinds of scripts to convert hi-res PNG image to a pleiad of different low-resolution copies may seem handy (and it really is), one should not forget that this kind of automatic resizing will render perceptibly imperfect images.
Lesser the resolution — blurrier the icon!
I mean, I love imagemagick too, but it is not the right tool for this task!
Instead, you should always request a logo in some vector format from your designer, for example in SVG. With this on hand, you can manually prepare perfect PNG files in all required resolutions and then make a single .icns file, which will make your app icon look beautiful on every single screen, from a cheap iPhone SE to some high-end Retina display of the latest iMac. You can use Photoshop, GIMP or any other tool of your choice to generate these PNGs.
From the latest Apple's Human Interface Guidelines as of 2020, you should prepare the following PNG files:
+---------------------+--------------------+--------------+
| filename | resolution, pixels | density, PPI |
+---------------------+--------------------+--------------+
| icon_16x16.png | 16x16 | 72 |
| icon_16x16#2x.png | 32x32 | 144 |
| icon_32x32.png | 32x32 | 72 |
| icon_32x32#2x.png | 64x64 | 144 |
| icon_128x128.png | 128x128 | 72 |
| icon_128x128#2x.png | 256x256 | 144 |
| icon_256x256.png | 256x256 | 72 |
| icon_256x256#2x.png | 512x512 | 144 |
| icon_512x512.png | 512x512 | 72 |
| icon_512x512#2x.png | 1024x1024 | 144 |
+---------------------+--------------------+--------------+
After all the PNG files are prepared, place them into some directory with .iconset extension (Logos.iconset for example) and execute the following from the Terminal:
iconutil --convert icns Logos.iconset
If there were no errors after executing this command, then all the files were processed properly, and you got the Logos.icns file in the same directory, containing all the beautiful crisp logos for your app which will suit any modern screen.

There's a command-line node module that does all the work of converting a PNG file into an iconset directory:
npm install -g node-icns
nicns --in adventure-cat.png --out adventure-cat.icns

These commands (entered in Terminal) worked for me to convert an old icns file to the new format:
cd Folder_With_Icns_File
iconutil -c iconset Your_Icon_Name.icns
rm Your_Icon_Name.icns
iconutil -c icns Your_Icon_Name.iconset
rm -R Your_Icon_Name.iconset
Update
The -c parameter to iconutil is no longer supported. Use --convert instead:
cd Folder_With_Icns_File
iconutil --convert iconset Your_Icon_Name.icns
rm Your_Icon_Name.icns
iconutil --convert icns Your_Icon_Name.iconset
rm -R Your_Icon_Name.iconset

Additional comment, when you create .icns file, you need to rename all the pic files with prefix "icon_", otherwise, iconutil will fail with error message: ".iconset:error: Failed to generate ICNS." which is not informative at all.

Same as #Henry (comment above) but takes as argument the PNG filename and outputs the ICNS with the same name.
NOTE : The PNG file name is only expected to have 1 point to separate extension, i.e. xpto.png .
(updated for shell script)
So, save the code below to a filed called "CreateICNS.sh" in the folder where your png file is, and give it execution permisisons.
Code:
#!/bin/bash
IFS='.' read -ra ADDR <<< "$1"
ICONSET=${ADDR[0]}.iconset
mkdir $ICONSET
sips -z 16 16 $1 --out $ICONSET/icon_16x16.png
sips -z 32 32 $1 --out $ICONSET/icon_16x16#2x.png
sips -z 32 32 $1 --out $ICONSET/icon_32x32.png
sips -z 64 64 $1 --out $ICONSET/icon_32x32#2x.png
sips -z 128 128 $1 --out $ICONSET/icon_128x128.png
sips -z 256 256 $1 --out $ICONSET/icon_128x128#2x.png
sips -z 256 256 $1 --out $ICONSET/icon_256x256.png
sips -z 512 512 $1 --out $ICONSET/icon_256x256#2x.png
sips -z 512 512 $1 --out $ICONSET/icon_512x512.png
cp $1 $ICONSET/icon_512x512#2x.png
iconutil -c icns $ICONSET
rm -R $ICONSET
HOW TO USE :
Then in the terminal, "cd" to the same folder and type :
./CreateICNS.sh {PNG filename}
where {PNG filename} is the name of your PNG file, i.e. xpto.png .
If your file would be named abc.png you would use :
./CreateICNS.sh abc.png
UPDATE 2021-05-20 :
I have an updated version of this but I'm not sure where I found it to leave here the correct reference so if someone is the owner of this or knows a link on some internet page, please comment so I can update credits :
This is a complete bash script, so you should save it as for example png2icns.sh and give it execution permissions.
Then you can call png2icns.sh pngfile1.png and it will generate the ICNS file as well as a iconset folder containing all icon resolutions between 16x16 and 512x512 .
#!/bin/bash
# Creates an icns file from a source image
src_image="$1"
if [ -z "$1" ]; then
echo "No source image was passed to this script"
exit 1
fi
icns_name="$2"
if [ -z "$2" ]; then
icns_name="iconbuilder"
fi
if [ "${src_image:(-3)}" != "png" ]; then
echo "Source image is not a PNG, making a converted copy..."
/usr/bin/sips -s format png "$src_image" --out "${src_image}.png"
if [ $? -ne 0 ]; then
echo "The source image could not be converted to PNG format."
exit 1
fi
src_image="${src_image}.png"
fi
iconset_path="./${icns_name}.iconset"
if [ -e "$iconset_path" ]; then
/bin/rm -r "$iconset_path"
if [ $? -ne 0 ]; then
echo "There is a pre-existing file/dir $iconset_path the could not be deleted"
exit 1
fi
fi
/bin/mkdir "$iconset_path"
icon_file_list=(
"icon_16x16.png"
"icon_16x16#2x.png"
"icon_32x32.png"
"icon_32x32#2x.png"
"icon_128x128.png"
"icon_128x128#2x.png"
"icon_256x256.png"
"icon_256x256#2x.png"
"icon_512x512.png"
"icon_512x512#2x.png"
)
icon_size=(
'16'
'32'
'32'
'64'
'128'
'256'
'256'
'512'
'512'
'1024'
)
counter=0
for a in ${icon_file_list[#]}; do
icon="${iconset_path}/${a}"
/bin/cp "$src_image" "$icon"
icon_size=${icon_size[$counter]}
/usr/bin/sips -z $icon_size $icon_size "$icon"
counter=$(($counter + 1))
done
echo "Creating .icns file from $iconset_path"
/usr/bin/iconutil -c icns "$iconset_path"
if [ $? -ne 0 ]; then
echo "There was an error creating the .icns file"
exit 1
fi
echo "Done"
exit 0

I have written a bash script for making icns from a svg file:
#!/usr/bin/env bash
sizes=(16 32 64 128 256 512)
largfile='icon_512x512#2x.png'
if [ ! -f "$largfile" ]; then
convert -background none -resize 1024x1024 "$1" "$largfile"
fi
for s in "${sizes[#]}"; do
echo $s
convert -background none -resize ${s}x${s} "$largfile" "icon_${s}x$s.png"
done
cp 'icon_32x32.png' 'icon_16x16#2x.png'
mv 'icon_64x64.png' 'icon_32x32#2x.png'
cp 'icon_256x256.png' 'icon_128x128#2x.png'
cp 'icon_512x512.png' 'icon_256x256#2x.png'
mkdir icon.iconset
mv icon_*x*.png icon.iconset
iconutil -c icns icon.iconset
Make sure you have imagemagick installed with librsvg support, on mac:
brew install imagemagick --with-librsvg
This script has served me quite well.
Update
For a more thorough treatment, I have created a command line tool (written in Swift) for generating AppIcon.appiconset with the correct layout and format:
https://github.com/kindlychung/genicon

I've refactored #Henry's script to make it look better:
#!/bin/zsh
NAME=$(basename $1 .png); DIR="$NAME.iconset"
mkdir -pv $DIR
for m r in 'n' '' '((n+1))' '#2x'; do
for n in $(seq 4 9 | grep -v 6); do
p=$((2**$m)); q=$((2**$n))
OUT="$DIR/icon_${q}x${q}${r}.png"
sips -z $p $p $1 --out $OUT
done
done
iconutil -c icns $DIR
rm -frv $DIR
Update
The -c parameter to iconutil is no longer supported. Use -—convert instead:
#!/bin/zsh
NAME=$(basename $1 .png); DIR="$NAME.iconset"
mkdir -pv $DIR
for m r in 'n' '' '((n+1))' '#2x'; do
for n in $(seq 4 9 | grep -v 6); do
p=$((2**$m)); q=$((2**$n))
OUT="$DIR/icon_${q}x${q}${r}.png"
sips -z $p $p $1 --out $OUT
done
done
iconutil -—convert icns $DIR
rm -frv $DIR

Dead simple .png 👉 .icns
Download IconMaker.app - It's just an .applescript won't bite
Drag and drop your .png onto the IconMaker.app you just created.
More info:
http://eon.codes/blog/2016/12/06/Creating-an-app-icon/
High sierra update iconutil is now more strict about the source .png size. More about this in the blog post after the jump. ✌️

When I'm validating my app I get this error:
the application bundle does not contain an icon in ICNS format, containing both a 512x512 and a 512x512#2x image.
⋮
I am not very good with terminal command and so maybe I'm doing something wrong. I wrote:
iconutil -c icns </Users/myname/SDK Mac Apps/MyApp/grafica/icon.iconset>
For one thing, as I mentioned in a comment on Anne's answer, you probably don't need to use iconutil. You should be able to just add the iconset to your project and let Xcode convert it for you as part of the build.
Either way, this may be your problem:
I tryed to put two PNG files togheter (512x512 and 1024x1024) … but I always get the error.
There is no 1024 by 1024 point size. The 1024 by 1024 pixel element (which was 1024 points before Mountain Lion) is now used for 512 by 512 points #2x.
Your PNG file must be named appropriately: icon_512x512#2x.png

Apple's older Icon Composer version 2.2 works just fine, you just open the .ICNS in it, press the 1024x1024 button and add your image.

#dardo82's shell code is good & worked.
Here is a simpler one in sh (for all *nix's) and faster (like it really matters):
#!/bin/sh
# This runs silent, be as verbose as you wish
NAME=$(basename ${1} .png)
DIR="${NAME}.iconset"
mkdir -p ${DIR}
for i in 16 32 128 256 512 ; do
x=""
for p in $i $(($i+$i)) ; do
sips -z $p $p ${1} --out "${NAME}.iconset/icon_${i}x${i}${x}.png"
x="#2x"
done
done >/dev/null # /dev/null in lieu of a "-s" silent option
iconutil -—convert icns $DIR
rm -r $DIR

Here's a function mostly based off Henry's example (could be useful in ~/.bash_profile):
mkicns() {
if [[ -z "$*" ]] || [[ "${*##*.}" != "png" ]]; then
echo "Input file invalid"
else
filename="${1%.*}"
mkdir "$filename".iconset
for i in 16 32 128 256 ; do
n=$(( i * 2 ))
sips -z $i $i "$1" --out "$filename".iconset/icon_${i}x${i}.png
sips -z $n $n "$1" --out "$filename".iconset/icon_${i}x${i}#2x.png
[[ $n -eq 512 ]] && \
sips -z $n $n "$1" --out "$filename".iconset/icon_${n}x${n}.png
(( i++ ))
done
cp "$1" "$filename".iconset/icon_512x512#2x.png
iconutil -c icns "$filename".iconset
rm -r "$filename".iconset
fi
}
Usage:
$ mkicns "filename.png" # double-quote if spaces exist in filename
Creates 10 sizes from 16x16 to 512x512#2x; accepts input images in
.png format only.

Run iconutil -c icns Icon.iconset
Note
Icon.iconset is a folder
Name start with lowercase icon_
When you see Icon.icns with correct image, you know it works

There are 2 tasks:
- create 10 correct icns files
- get your Xcode project to use them correctly
As I had hour long problems with both of these tasks, and also do not like when I don't 'see' what is going on, here a path for the cautious ones:
Create 10 correct icns files:
I used the script above from Henry: It still works for HighSierra and Xcode 9.2, including the 'c' command.
The icns file I got, appeared as only one icon size in Finder/Quicklook and in Preview showed only 8 of 10 sizes.
So I used terminal, went with cd to my folder and used the command: iconutil -c iconset (icns filename) on the just created icns file to revert the icns file back to an iconset folder, and - lo & behold - I could see my newly created 10 icon files. Using Quick look on the iconset folder (and using full screen mode to be able to zoom through them with the slider), I could check that all sizes are actually looking very well.
As an aside: they looked better than my resizing attempts with PSE, most likely because I did not take the time to play with all the resizing options in PSE. If you do use PSE, make sure your png files are saved without colour profile. Also, confessing my ignorance, for me a 256x256#2 file is the same as a 512x512 file - both in 72dpi. Trying to follow the 144 dpi comments above did not work for me.
Get your Xcode project to use them correctly:
First I deleted all my fruitless attempts within Xcode and committed a clean version to the git repository (what would have been clever, would have been to commit a clean version first - before I frantically started the icon addition odyssee).
I also made sure that in the info.plist file there is no pointer linked to the 'icon file' entry and that in my General project settings I had chosen AppIcon for App Icons.
Then I added an assets.asset catalog and within the assets catalog a new 'AppIcons and Launch Images' AppIcon Folder for OS.
Then I copied (drag and drop with option pressed) from the iconset folder each png picture file into the respective AppIcon Spaceholder. So again, I could see what is happening. Xcode did convert that into icns files, or maybe - as my iconset folder derived from an icns folder - the file formats were accepted.
Then archive and validate and there will be no errors upon uploading or validating.

I needed this, but for CMake. I also wanted the option of giving it an SVG.
Here is the gist: https://gist.github.com/Qix-/f4090181e55ea365633da8c3d0ab5249
And the CMake code:
# LICENSE: CC0 - go nuts.
# Hi :) This is what I used to generate the ICNS for my game, Tide.
# Both input formats (SVG vs PNG) work just fine, but in my experience
# the SVG came out with noticeably better results (although PNG wasn't
# a catastrophe either). The logo for the game was simple enough that
# SVG was indeed an option.
# To use:
#
# make_icns( INPUT "path/to/img.{svg,png}"
# OUTPUT ICNS_PATH )
#
# Then add it as a custom target or use it as a
# dependency somewhere - I give you that option.
#
# For example:
#
# add_custom_target( my-icns ALL DEPENDS "${ICNS_PATH}" )
#
# For the associated utilities:
#
# - PNG: brew install imagemagick
# - SVG: brew cask install inkscape
#
# Enjoy!
function (make_icns_from_png)
cmake_parse_arguments (
ARG
"" # Boolean args
"INPUT;OUTPUT" # List of single-value args
"" # Multi-valued args
${ARGN})
find_program (
convert_exe
NAMES "convert" "convert.exe"
DOC "Path to ImageMagick convert")
if (NOT convert_exe)
message (FATAL_ERROR "Could not find ImageMagick's 'convert' - is ImageMagick installed?")
endif ()
get_filename_component (ARG_INPUT_ABS "${ARG_INPUT}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
get_filename_component (ARG_INPUT_ABS_BIN "${ARG_INPUT}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
get_filename_component (ARG_INPUT_FN "${ARG_INPUT_ABS_BIN}" NAME_WE)
get_filename_component (ARG_INPUT_DIR "${ARG_INPUT_ABS_BIN}" DIRECTORY)
set (sourceimg "${ARG_INPUT_ABS}")
set (basepath "${ARG_INPUT_DIR}/${ARG_INPUT_FN}")
set (output_icns "${basepath}.icns")
set (iconset "${basepath}.iconset")
set (deplist "")
foreach (size IN ITEMS 16 32 128 256 512)
math (EXPR size2x "2 * ${size}")
set (ipath "${iconset}/icon_${size}x${size}.png")
set (ipath2x "${iconset}/icon_${size}x${size}#2x.png")
list (APPEND deplist "${ipath}" "${ipath2x}")
add_custom_command (
OUTPUT "${ipath}"
COMMAND "${convert_exe}" ARGS "${sourceimg}" -resize "${size}x${size}" "${ipath}"
MAIN_DEPENDENCY "${sourceimg}"
COMMENT "ICNS resize: ${ipath}"
VERBATIM)
add_custom_command (
OUTPUT "${ipath2x}"
COMMAND "${convert_exe}" ARGS "${sourceimg}" -resize "${size2x}x${size2x}" "${ipath2x}"
MAIN_DEPENDENCY "${sourceimg}"
COMMENT "ICNS resize: ${ipath2x}"
VERBATIM)
endforeach ()
add_custom_command (
OUTPUT "${output_icns}"
COMMAND iconutil ARGS --convert icns --output "${output_icns}" "${iconset}"
MAIN_DEPENDENCY "${sourceimg}"
DEPENDS ${deplist}
COMMENT "ICNS: ${output_icns}"
VERBATIM)
if (ARG_OUTPUT)
set ("${ARG_OUTPUT}" "${output_icns}" PARENT_SCOPE)
endif ()
endfunction ()
function (make_icns_from_svg)
cmake_parse_arguments (
ARG
"" # Boolean args
"INPUT;OUTPUT" # List of single-value args
"" # Multi-valued args
${ARGN})
set (CMAKE_FIND_APPBUNDLE NEVER) # otherwise, it'll pick up the app bundle and open a shit ton of windows
find_program (
inkscape_exe
NAMES "inkscape" "inkscape.exe"
DOC "Path to Inkscape"
PATHS "/usr/local/bin" "/usr/bin")
message (STATUS "Inkscape path: ${inkscape_exe}")
if (NOT inkscape_exe)
message (FATAL_ERROR "Could not find Inkscape - is it installed?")
endif ()
get_filename_component (ARG_INPUT_ABS "${ARG_INPUT}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
get_filename_component (ARG_INPUT_ABS_BIN "${ARG_INPUT}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
get_filename_component (ARG_INPUT_FN "${ARG_INPUT_ABS_BIN}" NAME_WE)
get_filename_component (ARG_INPUT_DIR "${ARG_INPUT_ABS_BIN}" DIRECTORY)
set (sourceimg "${ARG_INPUT_ABS}")
set (basepath "${ARG_INPUT_DIR}/${ARG_INPUT_FN}")
set (output_icns "${basepath}.icns")
set (iconset "${basepath}.iconset")
set (deplist "")
foreach (size IN ITEMS 16 32 128 256 512)
math (EXPR size2x "2 * ${size}")
set (ipath "${iconset}/icon_${size}x${size}.png")
set (ipath2x "${iconset}/icon_${size}x${size}#2x.png")
list (APPEND deplist "${ipath}" "${ipath2x}")
add_custom_command (
OUTPUT "${ipath}"
COMMAND "${inkscape_exe}" ARGS -z -e "${ipath}" -w ${size} -h ${size} "${sourceimg}"
MAIN_DEPENDENCY "${sourceimg}"
COMMENT "ICNS resize: ${ipath}"
VERBATIM)
add_custom_command (
OUTPUT "${ipath2x}"
COMMAND "${inkscape_exe}" ARGS -z -e "${ipath2x}" -w ${size2x} -h ${size2x} "${sourceimg}"
MAIN_DEPENDENCY "${sourceimg}"
COMMENT "ICNS resize: ${ipath2x}"
VERBATIM)
endforeach ()
add_custom_command (
OUTPUT "${output_icns}"
COMMAND iconutil ARGS --convert icns --output "${output_icns}" "${iconset}"
MAIN_DEPENDENCY "${sourceimg}"
DEPENDS ${deplist}
COMMENT "ICNS: ${output_icns}"
VERBATIM)
if (ARG_OUTPUT)
set ("${ARG_OUTPUT}" "${output_icns}" PARENT_SCOPE)
endif ()
endfunction ()
function (make_icns)
cmake_parse_arguments (
ARG
"" # Boolean args
"INPUT;OUTPUT" # List of single-value args
"" # Multi-valued args
${ARGN})
if (NOT ARG_INPUT)
message (FATAL_ERROR "INPUT is required")
endif ()
if (NOT IS_ABSOLUTE "${ARG_INPUT}")
get_filename_component (ARG_INPUT "${ARG_INPUT}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
endif ()
if (NOT EXISTS "${ARG_INPUT}")
message (FATAL_ERROR "INPUT does not exist: ${ARG_INPUT}")
endif ()
file (RELATIVE_PATH ARG_INPUT "${CMAKE_CURRENT_SOURCE_DIR}" "${ARG_INPUT}")
get_filename_component (ARG_INPUT_EXT "${ARG_INPUT}" EXT)
if ("${ARG_INPUT_EXT}" STREQUAL ".png")
make_icns_from_png (INPUT "${ARG_INPUT}" OUTPUT child_output)
elseif ("${ARG_INPUT_EXT}" STREQUAL ".svg")
make_icns_from_svg (INPUT "${ARG_INPUT}" OUTPUT child_output)
else ()
message (FATAL_ERROR "INPUT must refer to a .png or .svg, but a ${ARG_INPUT_EXT} was provided")
endif ()
if (ARG_OUTPUT)
set ("${ARG_OUTPUT}" "${child_output}" PARENT_SCOPE)
endif ()
endfunction ()

Hello, for my needs I made a droplet that works in drag and drop icons alone or icons to search in a folder (I limited to folders as the searches on Volumes of all the icons can take a lot of time ). So in drag and drop you can drop folders or application, anything that can contain an icon. The iconset created bears the name of the original icon, it is placed in a directory "/ aaaicones" and the path of the icon. Example in the folder "/ aaaicones if you submit xcode.app you will find
"/aaaicones/Applications/xcode.app/access.iconset" and /aaaicones/Applications/xcode.app/access.icns (the recreated icon) there will be a text file where it is traced the full path of the icons , And the path to the corresponding iconset example
"/Applications/xcode.app/Contents/Applications/Instruments.app/Contents/Frameworks/InstrumentsPlugIn.framework/Versions/A/Resources/access.icns"
"/aaaicones/Applications/xcode.app/access.iconset" in the example taken (xcode) this can create a folder at the end (with all icons and iconset) of 214 MB in size. If you treat an icon alone, it will be placed in the directory "/ aaaicones / aIconeseule /" and its original path, example
/aaaicones/aIconeseule/Mac Elcapitan/.VolumeIcon.icns and /aaaicones/aIconeseule/Mac Elcapitan /.VolumeIcon.iconset with /aaaicones/aIconeseule/Mac Elcapitan/aalisticones.txt
The droplet is below
on open draggedItems
set input to draggedItems
set fich to draggedItems
set media to {}
set theInfo to {}
set n to "0"
repeat with currentItem in draggedItems
set dirchoisi to POSIX path of fich
if ".icns" is not in dirchoisi then
if "Volumes" is not in dirchoisi then
set origi to do shell script "echo /aaaicones" & dirchoisi
set fich to do shell script "echo " & fich & " | xxd -p -c 100000 | sed 's#3a#2f#g' | xxd -r -p | sed 's#" & dirchoisi & "#" & "/aaaicones" & dirchoisi & "#g' | xxd -p -c 100000 | sed 's#2f#3a#g' | xxd -r -p"
tell application "Finder"
if exists (folder fich) then
set nn to "0"
repeat with nn from 1 to 5
set origi to do shell script "echo " & origi & "/" & " | sed 's#//#" & nn & "/" & "#'"
set fich to do shell script "echo " & fich & " | sed 's#:aaaicones*.*#" & origi & "#'" & " | xxd -p -c 100000 | sed 's#2f#3a#g' | xxd -r -p"
if not (exists folder (fich as Unicode text)) then
try
set origi to do shell script "echo " & origi
exit repeat
end try
end if
end repeat
end if
end tell
tell application "Finder"
if not (exists folder (fich as Unicode text)) then
do shell script "mkdir -p -m 0777 " & quoted form of origi
end if
end tell
try
set theInfo to do shell script "find " & (quoted form of dirchoisi) & " -name *.icns "
end try
set AppleScript's text item delimiters to return
set theList to text items of theInfo
set AppleScript's text item delimiters to ""
set n to count theList
repeat with i from 1 to n
if "Volumes" is not in item i of theList then
set end of media to item i of theList
end if
end repeat
set n to count media
set cheminicns to do shell script " > " & quoted form of (origi & "aalisticones.txt") & " | chmod 777 " & quoted form of (origi & "aalisticones.txt")
set cheminicns to do shell script "ls " & quoted form of (origi & "aalisticones.txt")
tell application "Finder"
set letext to (POSIX file cheminicns as alias)
set label index of letext to 2
end tell
repeat with i from 1 to n
set hdd to item i of media
try
set input to do shell script "echo " & hdd & " | sed 's#//#/#g; s#(#\\(#g;s#)#\\)#g' "
do shell script "echo " & quoted form of input & " >>" & quoted form of cheminicns
set png to do shell script "echo " & quoted form of input & " | sed 's#.*/##' "
do shell script "cp -f " & quoted form of input & " " & quoted form of origi
set input to do shell script "iconutil -c iconset " & quoted form of (origi & png)
do shell script "echo " & quoted form of (origi & png) & " | sed 's#.icns#.iconset#' >>" & quoted form of cheminicns
end try
end repeat
tell application "Finder"
if exists (folder fich) then
open fich
end if
end tell
end if
else
set input to do shell script "echo " & dirchoisi & " | sed 's#//#/#g; s#(#\\(#g;s#)#\\)#g' "
set png to do shell script "echo " & quoted form of input & " | sed 's#.*/##' "
set origi to do shell script "echo " & quoted form of ("/aaaicones/aIconeseule/" & input) & " | sed 's#/Volumes/##; s#" & quoted form of png & "##'"
do shell script "mkdir -p -m 0777 " & quoted form of origi
do shell script "echo " & quoted form of input & " >>" & quoted form of origi & "aalisticones.txt"
do shell script "cp -f " & quoted form of input & " " & quoted form of origi
set input to do shell script "iconutil -c iconset " & quoted form of (origi & png)
do shell script "echo " & quoted form of (origi & png) & " >>" & quoted form of origi & "aalisticones.txt"
end if
end repeat
end open

Related

How can one extract the format of a file that contains several periods? (Bash scripting) [duplicate]

This question already has answers here:
Extract filename and extension in Bash
(38 answers)
Closed 7 months ago.
I'm trying to make a file sorter. Ideas is, I used a program inotifywait to monitor my downloads directory and then find a file that has been moved into that directory. Once found I used the cut command to acquire the format of that file and then move this latter to a specific directory. Thing is, I'm having problems with files that, instead of spaces or " _ , - ", use period to separate words. I seek another way to acquire a file's format.
Here is the code:
#!/bin/bash
############################### Directory paths section
pictures=$HOME/media/pictures/
videos=$HOME/media/videos/
documents=$HOME/Documents/
downloads=$HOME/Downloads/
###############################
inotifywait -m $downloads -e moved_to |
while read dir action file; do
notify-send "File Detected!" "A file has been added to your downloads directory"
format=$(echo "$file" | cut -f 2 -d '.')
sleep 1s
case "$format" in # Add more formats if needed
"jpg" | "png" | "jpeg") # Image formats
mv $downloads$file $pictures
notify-send "'$file' has been moved to Pictures directory"
;;
"mp3" | "wav") # Music formats
mv $downloads$file $music
notify-send "'$file' has been moved to Music directory"
;;
"mp4" | "ogg") # Video formats
mv $downloads$file $videos
notify-send "'$file' has been moved to Videos directory"
;;
"doc" | "docx" | "pdf" | "html") # Document formats
mv $downloads$file $documents
notify-send "'$file' has been moved to Documents directory"
;;
*)
notify-send "File format not recongnized" "the file is kept in Downloads directory"
;;
esac
done
And if you have any improvements for suggestions please let me know. Thanks.
I think this is what you want to solve the specific problem you asked about:
$ for file in foo.png foo.bar.pdf foo.bar.png.pdf.jpg; do
suffix="${file##*.}"
echo "$file -> $suffix"
done
foo.png -> png
foo.bar.pdf -> pdf
foo.bar.png.pdf.jpg -> jpg
but please do run shellcheck on your code and fix the additional issues it tells you about.
Note that the above is just identifying the suffix a file has, that doesn't necessarily mean the file has any specific format since Unix doesn't use file suffixes to determine the format of a file, that's a Windows thing. A file that ends in .doc or .pdf could be plain text or an image or anything else. Try using the the command file to identify a files actual format instead.

How can I pass a large number of command line arguments to C++ program

I'm using OpenCV 3.2 in Ubuntu 16.04 to stitch airborne scanned images. The example software that I'm using accepts the images as command line arguments so in order to stitch two images together I do the following:
./main image1.jpg image2.jpg
My problem is that I have a total of 96 images to stitch. Do I need to input each of these images separately or is there a way to give all files contained in a folder as command line input to C++ program?
I have not been able to Google suitable answer to this so I decided to ask here.
You can make use of the shell file name expansion by entering
./main image*.jpg
image*.jpg will be expanded by the shell to all jpeg files starting with "image", similarly to ls image*.jpg.
So if you have 96 files called imageXX.jpg, your main program will receive all 96 files on the command line.
You can use this bash script
#!/bin/bash
dir_path=$1
if [ $# = 1 ]; then
if [ -d "${dir_path}" ] ; then
echo "$dir_path exists and is a directory";
else
echo "$dir_path is not a directory";
exit 1
fi
else
echo "Need one argument = directory";
exit 1
fi
echo "Process all files";
image_names=" ";
# concat all .jpg files in directory
FILES="$dir_path/*.jpg"
for f in $FILES
do
# echo "Processing $f file..."
image_names+=" $f"
done
echo "run ./main $image_names";
exec "./main $image_names";
save it as "runAllFiles.bash" in the directory that contains your "./main"
then open a terminal in this directory and write command line
bash runAllFiles.bash myfolder
Where "myfolder" is the path to your folder with images.jpg

Icon changing Script

i can't get this program to work with files with spaces in them.
it keeps erroring out even when i modify it for the code to have "\ " before every space
what happened was i found this code online and it works as a shell script when you send the info and the files have no spaces, now i'm trying to get it to work in automator and with any file
iconSource="$1"
iconDestination="$2"
newiconSource="${iconSource}"
newiconDestination="${iconDestination}"
echo $newiconSource
echo $newiconDestination
icon=/tmp/`basename $newiconSource`
rsrc=/tmp/icon.rsrc
# Create icon from the iconSource
cp $newiconSource $icon
# Add icon to image file, meaning use itself as the icon
sips -i $icon
# Take that icon and put it into a rsrc file
DeRez -only icns $icon > $rsrc
# Apply the rsrc file to
SetFile -a C $newiconDestination
if [ -f $newiconDestination ]; then
# Destination is a file
Rez -append $rsrc -o $newiconDestination
elif [ -d $newiconDestination ]; then
# Destination is a directory
# Create the magical Icon\r file
touch $newiconDestination/$'Icon\r'
Rez -append $rsrc -o $newiconDestination/Icon?
SetFile -a V $newiconDestination/Icon?
fi
Here's a simpler piece of code reproducing your problem:
file="hello world"
rm $file
This outputs:
rm: cannot remove `hello': No such file or directory
rm: cannot remove `world': No such file or directory
(if it doesn't, it just deleted your files named "hello" and "world". Sorry about that.)
To fix it, you have to double quote all references to variables to prevent globbing and wordsplitting:
file="hello world"
rm "$file" # <- Note double quotes
ShellCheck automatically points this out. Run your script through it, and it'll point out most of the references that need quoting.

Let user choose name of output file in bash

I have this script, that does several operations on some files, which then creates an output file in the end called flashable.zip.
I'd like to implement that when the user runs the script, it begins with asking for a filename to output in the end. The filename is predefined to looking like this: 1.22.33_DA.zip, where the user gets to choose the 1.22.33 part - It's like version naming the file.. And it has to be strict, so the user don't use letters in the 1.22.33 part..
I'm sure I can use something like grep for this, but I'm completely lost in how to do it :(
And I'm fairly new to bash scripting, so I'm still learning, the script I got might look pretty messy and can probably be cleaned up a bit :)
I'm thinking it would just be something that renames the created zipfile when the operations are done, but I'm not sure though..
Here's my script:
#!/bin/bash
echo ""
echo "[--- Creating flashable zip ---]"
echo ""
tlock=/home/dan/buildtool/flashable/template/system/media/theme/default
dst=/home/dan/buildtool/flashable/system/media/theme/default
src=/home/dan/buildtool/translations/ma-xml-4.0-danish/extras/lockscreen
parent=/home/dan/buildtool/flashable
src2=/home/dan/buildtool/apk_out
home=/home/dan/buildtool
cd $parent
mkdir system
cd system
mkdir app
mkdir framework
mkdir media
cd media
mkdir theme
mkdir audio
cd theme
mkdir default
cd $parent/system/media/audio
mkdir ringtones
mkdir alarms
mkdir notifications
cd $home
for apk in $(<$home/translation_list.txt); do cp -r -f "$src2/$apk" $parent/system/app; done
mv -f $parent/system/app/framework-miui-res.apk $parent/system/framework
cp -f $parent/template.zip $parent/flashable.zip
cp -f -r $parent/template/system/media/audio $parent/system/media
7za u -tzip $tlock/lockscreen.zip $src/advance
cp -f $tlock/lockscreen.zip $tlock/lockscreen
cp -f $tlock/lockscreen $dst
7za a -tzip $parent/flashable.zip $parent/system -mx3
rm -r $parent/system
cd /home/dan/buildtool
This will read in user input and validate the version via regex.
#!/bin/bash
echo -n "Enter version and press [ENTER]: "
read ver
[[ "$ver" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] && echo "${ver}_DA.zip" || echo "Invalid"
Output
Enter version and press [ENTER]: 111.222.333
111.222.333_DA.zip
Enter version and press [ENTER]: 1.2222.33
Invalid
Enter version and press [ENTER]: 1.222.3333
Invalid
Explanation
read ver Reads in user input into the ver variable.
^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$
1) ^ Start of string
2) [0-9] Any digit between 0 and 9
3) {1,3} Match at least 1 up to 3 characters
4) \. Match a dot
5) \.[0-9]{1,3} Repeat pattern twice
7) $ Match end of string

How to set icon on file or directory using CLI on OS X?

To set an icon on a file or directory is straight forward using the "Get Info" dialog in Finder.
copy image from e.g. Preview
open "Get Info" on file or directory
press TAB to select the icon
paste Cmd-V
But how do you do this using the command line?
Here is a bash script "setIcon.sh" for it
#!/bin/sh
# Sets an icon on file or directory
# Usage setIcon.sh iconimage.jpg /path/to/[file|folder]
iconSource=$1
iconDestination=$2
icon=/tmp/`basename $iconSource`
rsrc=/tmp/icon.rsrc
# Create icon from the iconSource
cp $iconSource $icon
# Add icon to image file, meaning use itself as the icon
sips -i $icon
# Take that icon and put it into a rsrc file
DeRez -only icns $icon > $rsrc
# Apply the rsrc file to
SetFile -a C $iconDestination
if [ -f $iconDestination ]; then
# Destination is a file
Rez -append $rsrc -o $iconDestination
elif [ -d $iconDestination ]; then
# Destination is a directory
# Create the magical Icon\r file
touch $iconDestination/$'Icon\r'
Rez -append $rsrc -o $iconDestination/Icon?
SetFile -a V $iconDestination/Icon?
fi
# Sometimes Finder needs to be reactivated
#osascript -e 'tell application "Finder" to quit'
#osascript -e 'delay 2'
#osascript -e 'tell application "Finder" to activate'
rm $rsrc $icon
Assuming that we have icns-file already. Create temp resource file which points to icns-file:
$ echo "read 'icns' (-16455) \"Icon.icns\";" >> Icon.rsrc
Append the resource file as value of extended attribute "com.apple.ResourceFork" to a file:
$ Rez -a Icon.rsrc -o FileName.ext
Show the icon of the file:
$ SetFile -a C FileName.ext
Append resource file as value of extended attribute "com.apple.ResourceFork" to a magic icon file inside current folder:
$ Rez -a Icon.rsrc -o Icon$'\r'
Show the icon of current folder:
$ SetFile -a C .
Hide the magic icon file inside current folder (press ⇧⌘. to show/hide hidden files in Finder):
$ SetFile -a V Icon$'\r'
Additional details
Icon data is stored as value of extended attribute "com.apple.ResourceFork" (Terminal command "xattr -p com.apple.ResourceFork FileName.ext" prints the value). For a folder there is magic (which is empty and hidden) file Icon$'\r' inside the folder. To extract icon data from extended attribute "com.apple.ResourceFork" into plain text resource file (from which we know correct icns-type identifier "-16455"):
$ DeRez -only icns FileWithIcon.ext > Icon.rsrc
$ DeRez -only icns /Folder/With/Icon/Icon$'\r' > Icon.rsrc
Under macOS 10.13 High Sierra command $ sips -i ImageFile.icns/png/jpg generates error --addIcon is no longer supported. Switch -i means "--addIcon" as extended attribute "com.apple.ResourceFork" onto this file itself using the content of this image file.

Resources