#!/usr/bin/perl -w # Copyright © 2015-2016 Dave Odell # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation. No representations are made about the suitability of this # software for any purpose. It is provided "as is" without express or # implied warranty. # This is a replacement for seticon from http://osxutils.sourceforge.net/. require 5; use diagnostics; use strict; #use IPC::Open2; use File::Temp; my $progname = $0; $progname =~ s@.*/@@g; my ($version) = ('$Revision: 1.7 $' =~ m/\s(\d[.\d]+)\s/s); my $verbose = 0; sub set_icon ($$) { my ($icon, $target) = @_; my $target_res = $target; if (-d $target) { $target_res = $target_res . "/Icon\r"; } # Rez hates absolute paths, apparently. if ($icon =~ m@^/@s) { my $cwd = `pwd`; chomp $cwd; $icon =~ s@^\Q$cwd/@@s; } # The Rez language is documented in "Building and Managing Programs in MPW, # Second Edition". No longer available on Apple's servers, it can now be # found at: # http://www.powerpc.hu/manila/static/home/Apple/developer/Tool_Chest/Core_Mac_OS_Tools/MPW_etc./Documentation/MPW_Reference/Building_Progs_In_MPW.sit.hqx my $pgm = "Read 'icns' (kCustomIconResource) \"$icon\";\n"; # Rez can read from stdin, but only if it is a file handle, not if it # is a pipe (OS X 10.9, Xcode 5; OSX 10.11, Xcode 6). my ($rez_fh, $rez_filename) = File::Temp::tempfile(DIR => '.', UNLINK => 1); print $rez_fh $pgm; close $rez_fh; my @cmd = ('Rez', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms' . '/MacOSX.platform/Developer/SDKs/MacOSX.sdk', 'CoreServices.r', $rez_filename, '-o', $target_res); print STDERR "$progname: exec: " . join(' ', @cmd) . "\n$pgm\n" if ($verbose); # my ($in, $out); # my $pid = open2 ($out, $in, @cmd); # print $in $pgm; # close ($in); # waitpid ($pid, 0); system (@cmd); my $exit = $? >> 8; exit ($exit) if $exit; # Have to also inform Finder that the icon is there, with the # com.apple.FinderInfo xattr (a FolderInfo struct). @cmd = ('SetFile', '-a', 'C', $target); system (@cmd); $exit = $? >> 8; exit ($exit) if $exit; } sub error($) { my ($err) = @_; print STDERR "$progname: $err\n"; exit 1; } sub usage() { print "Usage: $progname -d source [file...]\n"; exit 1; } sub main() { my ($src, @dst); while ($#ARGV >= 0) { $_ = shift @ARGV; if (m/^--?verbose$/s) { $verbose++; } elsif (m/^-v+$/s) { $verbose += length($_)-1; } elsif (m/^-d$/s) { $src = shift @ARGV; } elsif (m/^-/s) { usage(); } else { push @dst, $_; } } error ("no source") unless defined($src); error ("no files") unless @dst; foreach my $f (@dst) { set_icon ($src, $f); } } main(); exit 0;