Posted on 06-15-2012 09:57 AM
Hey Nation,
I wrote a script that I have been using to help find great icons for Self Service and thought I would share with the community. Below is a script that I wrote for helping you to find .icns files and change them into .png files for use with Self Service (both OS X and iOS). The script does have some variables that you will need to comment and uncomment to make it work. I tried to put in notes to make it easy to understand what is going on. In pseudo code this is what should happen:
Please note that this is my own work and does not come with any warranty or support.
Thanks,
Kyle
#!/bin/sh
#Tested with 10.7.4 on 6/15/2012
#Written by Kyle Bareis
#This script has no warranty. Use at your own risk!
#######################################################################################
################################### Read this part! ###################################
#######################################################################################
# Specifiy what type of icns files you are looking for files will be saved to the root
# of your drive. Only uncomment one below at a time. This script must be run in sudo!
# The folder will be created at the root of your local hard drive with all files in it
# Example: /Applications_icnsDump/
# Options are applications, system, or library.
#iconType=Applications
#iconType=Library
#iconType=System
#######################################################################################
############################ DON'T CHANGE BELOW THIS POINT ############################
#######################################################################################
#Makes directory for ICNS files
mkdir /"$iconType"_icnsDump/
#Creates file listing icon locations so that we can copy them
sudo find /"$iconType" -name "*.icns" > /"$iconType"_icnsDump/"$iconType"_DumpList.txt
#Sets the IFS to new lines so that we get proper returns in data
IFS=$'
'
#Loads file into a variable
fileList=( `cat "/"$iconType"_icnsDump/"$iconType"_DumpList.txt" `)
#Variaible for Counting the files
int=0
#For do loop to crank over each line of data and copy it into the folder made above
for i in "${fileList[@]}"
do
sudo cp "$i" /"$iconType"_icnsDump/
int=$(($int+1))
done
#Coverting ICNS to PNG
#Creating folder to put the PNG files
mkdir /"$iconType"_pngDump/
#SIPS command to convert the files and resize.
#Sending Warnings to dev/null
sudo sips -s format png --resampleHeight 128 /"$iconType"_icnsDump/*.icns --out /"$iconType"_pngDump > /dev/null 2>&1
echo "Congrats! you have new ICNS and PNG files"
echo "You found $int Files that have been converted"
echo "ICNS files are in /"$iconType"_icnsDump/"
echo "PNG files are in /"$iconType"_pngDump"
Posted on 06-15-2012 10:17 AM
Thanks Kyle. I'll save this.
Posted on 06-15-2012 11:04 AM
Awesome work Kyle!! I didn't even know what half of these icons were from!
Posted on 06-15-2012 11:12 AM
@Kelly
If you check out the .txt file that is saved into the icnsDump folder you can see were they come from!
Kyle
Posted on 06-15-2012 12:24 PM
Nice script Kyle!
It works well. Only thing is, in addition to lots of good usable icons, you also end up with lots of very small pixelated icons that can't really be used in Self Service, unless you're OK with chunky old school looking icons :)
I see that the sips tool has an option to read the pixel dimensions with something like-
sips --getProperty pixelHeight /path/to/image.icns
Maybe in a "version 2" you can add in an optional check to only convert icons that have at least 128 pixel dimensions or bigger, to weed out all those small UI elements. And if/then type loop should be able to do it.
Good work though. Thanks.
Posted on 06-15-2012 02:00 PM
@ mm2270
Thanks! The sips add-on was a last minute edition before I posted, but I agree with you about the pixels. What would be really nice would be to read out the pixels and only convert ones that are large enough thereby getting rid of the junk. Down the road it might be cool to flag certain directories as garbage too!
Thanks again,
Kyle
Posted on 06-18-2012 08:42 AM
Kyle,
Nice bit of work! You can never have too many icons.
Gary
Posted on 06-22-2012 08:33 PM
I saw this at the end of the day today and think it is pretty awesome. My utilities for doing this required Rosetta and opening up things in Preview or Photoshop to change them is annoying. Thanks for showing me sips!
There are some issues though and I took whack at them after dinner.
A couple of minor things that can be tweaked. The need for intermediate files can go and I figured it was pretty easy to see the count in Finder after the script is done so I dropped that. I also wanted to get rid of the sudo in the script itself and make it so that you don't have to change the variable to modify the search location.
The biggest problem is this though:
#Sets the IFS to new lines so that we get proper returns in data
Technically filenames CAN have newlines in them. So while setting IFS to only be newlines and can, in certain situations, solve problems with spaces we want to always use find with -print0, mdfind with -0 etc. because there are definitely NOT null characters. :)
See http://mywiki.wooledge.org/ParsingLs for more info.
Here is a specific example using find:
ryan@SIS-27-RMANLY ~ $ mkdir test
ryan@SIS-27-RMANLY ~ $ cd test
ryan@SIS-27-RMANLY test $ touch file$'
'name
ryan@SIS-27-RMANLY test $ ls
file?name
ryan@SIS-27-RMANLY test $ ls -l
total 0
-rw-r--r-- 1 ryan staff 0 Jun 22 21:26 file?name
ryan@SIS-27-RMANLY test $ while read -r i; do
> mv "$i" test1
> done< <(find . -name "fi*")
mv: rename ./file to test1: No such file or directory
mv: rename name to test1: No such file or directory
ryan@SIS-27-RMANLY test $ while IFS=$'
' read -r i; do
> mv "$i" test2
> done< <(find . -name "fi*")
mv: rename ./file to test2: No such file or directory
mv: rename name to test2: No such file or directory
ryan@SIS-27-RMANLY test $ while read -r -d $'' i; do
> mv "$i" test3
> done< <(find . -name "fi*" -print0)
ryan@SIS-27-RMANLY test $ ls
test3
So, while extremely unlikely it could be terribly dangerous. I got bitten by something similar when I scripted out some filename migration stuff from a database export for a radio station. I got the CSV conversion from an old dBase file off of a Windows machine and ended up with carriage returns in filenames all over the place because I wasn't thinking about them not being newlines.
Bad news. Got a quick fix from the guy who runs the http://mywiki.wooledge.org/BashGuide wiki though :D
AND FINALLY!
Here is my version of the Icon Finder/Converter
#!/bin/bash
###############################################################
# Self Service Icon Finder/Converter #
# inspired by Kyle Bareis' work here #
# https://jamfnation.jamfsoftware.com/discussion.html?id=4681 #
# #
# Ryan Manly, 06/22/12 #
# #
# NOTE: must run with sudo to poke around in /System etc. ;) #
###############################################################
# create some variables so we don't have nasty long paths to deal with later
icnsdir="${HOME}/Desktop/newicons/icns"
pngdir="${HOME}/Desktop/newicons/png"
# get username so we can fix ownership on newicons directory after we are done
user=$(stat -f "%Su" /dev/console)
# create our destination directoriess on the Desktop
mkdir -p "${HOME}/Desktop/newicons/"{icns,png}
# define function to call later in case/esac
# read in the output of find using null as the delimiter in case there are
# spaces etc. in file names. When a match is found copy it to $icnsdir
# created on the desktop, then convert it and place output png in $pngdir
# all files and directoriess are owned by root...fix that
search() {
while read -r -d $'' icnsfile; do
cp "${icnsfile}" "${icnsdir}"
sips -s format png --resampleHeight 128 "${icnsfile}" --out "${pngdir}" &> /dev/null
done< <(find "${location}" -iname "*.icns" -print0)
chown -R "$user" "${HOME}/Desktop/newicons"
}
# define menu function so we can display the menu again easily if the input is invalid
menu() {
echo "Where should I look for icons?"
echo "[A]pplications, [L]ibrary, [S]ystem, or [Q]uit"
read -r input
# If input is 'A' or 'a' followed by anything set location
# for find to search only in the /Applications directory, then
# call the search function. If input does not match any criteria
# display error message and then the menu again.
case "${input}" in
[Aa]*)
location='/Applications'
search
;;
[Ll]*)
location='/Library'
search
;;
[Ss]*)
location='/System'
search
;;
[QqXx]*)
echo "Quit"
exit 0
;;
*)
echo
echo -e "${input} was not a valid option!"
menu
;;
esac
}
# finally call our menu function and get to work
menu
Posted on 06-28-2012 09:40 AM
@rmanly
Cool looking edits! I have yet to download it and play but it looks like you took a thought and made it into a thesis! Thanks for taking a look at it and extending it.
As a sidebar note, I was doing some additional playing around on a v.2 and came up with some of the same enhancements you had done. Below are some mods I did to the original. The big difference in this version (other then asking the user instead of requiring editing text was the inclusion of folder so that you know were the icns files are coming from. ** currently sips is not integrated into this script **
#!/bin/sh
# Tested with 10.7.4 on 6/19/2012
# Written by Kyle Bareis
# This script is provided “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
# IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
# OR FITNESS FOR A PARTICULAR PURPOSE.
#######################################################################################
################################### Read this part! ###################################
#######################################################################################
# Specifiy what type of icns files you are looking for files will be saved to the
# $HOME/Desktop of your drive. This script must be run in sudo!
#######################################################################################
############################ DON'T CHANGE BELOW THIS POINT ############################
#######################################################################################
# Start of script and asking user for folder they wish to search
clear
echo "#######################################################################################"
echo ""
echo ""
echo "Please the path you would like to search: "
echo "Example: /Applications or /System/Library"
echo ""
read iconPath
echo ""
echo "You entered: $iconPath"
echo ""
# Verification that that is the correct folder
while true; do
read -p "Are you sure this is the path you want to look in?
Please enter y for yes or n for no: " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) exit;;
* ) echo "
### Invalid Entry ###
You entered: $iconPath
";;
esac
done
clear
echo "#######################################################################################"
#Makes directory for ICNS files
echo ""
echo ""
mkdir -p $HOME/Desktop/icnsDump
echo "Created $HOME/Desktop/icnsDump"
#Creates file listing icon locations so that we can copy them
echo ""
echo ""
sudo find "$iconPath" -name "*.icns" > $HOME/Desktop/icnsDump/dumpList.txt
echo "Found icns files at $iconPath and created a list of them at"
echo "$HOME/Desktop/icnsDump/dumpList.txt"
#Sets the IFS to new lines so that we get proper returns in data
IFS=$'
'
#Loads file into a variable
echo ""
echo ""
fileList=( `cat "$HOME/Desktop/icnsDump/dumpList.txt" `)
echo "Files loaded into the script and preparing to copy"
#Variaible for Counting the files
count=0
#For do loop to crank over each line of data and copy it into the folder made above
for i in "${fileList[@]}"
do
count=$(($count+1))
idir=`echo $i | awk '{gsub(/./,"");print}'`
mkdir -p $HOME/Desktop/icnsDump/$idir
sudo cp "$i" $HOME/Desktop/icnsDump/$idir
done
echo ""
echo ""
echo "Congrats! you have new ICNS files"
echo "You found $count icns files that have been copied"
echo "ICNS files are in $HOME/Desktop/icnsDump/"
echo ""
echo ""
echo "#######################################################################################"
Kyle