Welcome

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

What next?
1. Bookmark us with del.icio.us or Digg Us!
2. Subscribe to this site's RSS feed
3. Browse the site.
4. Post your own code snippets to the site!

Create an installer package for a shell script

Requires Xcode.

# "Package a single item for installation"
open -a 'Help Viewer' /Developer/Applications/Utilities/PackageMaker.app/Contents/Resources/English.lproj/Help_Book/html/contents.html


find /Library/Receipts -name "*.bom" | grep -i myapp || echo 'You can go on!'
ls -l /usr/local/bin/hello.sh 2>/dev/null || echo 'You can go on!'


# create a package directory structure to create an installer package for hello.sh

function pkgdir() {


# "Note: you will not need to make directories below Package_root that your package does not need."
# see: http://www.osxgnu.org/info/osxpackages.html
# (so in fact we could do without ...Package_Root/usr/bin, ...Package_Root/Applications and ...Package_Root/private/etc)

: <<-'COMMENT'
/bin/mkdir -p \
     ~/Desktop/Distribution_folder/Package_Root/usr/local/bin \
     ~/Desktop/Distribution_folder/Resources
COMMENT


/bin/mkdir -p \
     ~/Desktop/Distribution_folder/Package_Root/usr/local/bin \
     ~/Desktop/Distribution_folder/Package_Root/usr/bin \
     ~/Desktop/Distribution_folder/Package_Root/Applications \
     ~/Desktop/Distribution_folder/Package_Root/private/etc \
     ~/Desktop/Distribution_folder/Resources


# also create a directory where the installer package for hello.sh below will be created
/bin/mkdir -p ~/Desktop/MyApp 

declare EX_MARK='!'

/bin/cat > ~/Desktop/Distribution_folder/Resources/Info.plist <<-EOF
<?xml version="1.0" encoding="UTF-8"?>
<${EX_MARK}DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>CFBundleGetInfoString</key>
        <string>hello-1.1.1</string>
        <key>CFBundleIdentifier</key>
        <string>org.myhome.myapp</string>
        <key>CFBundleName</key>
        <string>hello.sh</string>
        <key>CFBundleShortVersionString</key>
        <string>1.1.1</string>
        <key>IFPkgFlagAuthorizationAction</key>
        <string>RootAuthorization</string>
        <key>IFPkgFlagDefaultLocation</key>
        <string>/</string>
        <key>IFPkgFlagFollowLinks</key>
        <false/>
        <key>IFPkgFlagRootVolumeOnly</key>
        <true/>
</dict>
</plist>
EOF


/bin/cat > ~/Desktop/Distribution_folder/Resources/Welcome.txt <<-'EOF'
This is my welcome message!
EOF

/bin/cat > ~/Desktop/Distribution_folder/Resources/License.txt <<-'EOF'
The MIT License
EOF

/bin/cat > ~/Desktop/Distribution_folder/Resources/ReadMe.txt <<-'EOF'
Read me!
EOF


# hello.sh 
/bin/cat > ~/Desktop/Distribution_folder/Package_Root/usr/local/bin/hello.sh <<-'EOF'
#!/bin/bash
echo hello
exit 0
EOF


# postflight
# taken from: open /Developer/Applications/Utilities/PackageMaker.app/Contents/Resources/English.lproj/Help_Book/package/scripts.html
/bin/cat > ~/Desktop/Distribution_folder/Resources/postflight <<-'EOF'
#!/bin/bash
#
# This postflight script echoes the values of the available 
# arguments and environmental variables.
#
/usr/bin/logger -i "Start postflight script"
/usr/bin/logger -i ""
/usr/bin/logger -i "Arguments:"
/usr/bin/logger -i ""
/usr/bin/logger -i "\$1: full path to the installation package"
/usr/bin/logger -i "     $1"
/usr/bin/logger -i "\$2: full path to the installation destination"
/usr/bin/logger -i "     $2"
/usr/bin/logger -i "\$3: mountpoint of the destination volume"
/usr/bin/logger -i "     $3"
/usr/bin/logger -i "\$4: root directory \"/\" for the current System folder"
/usr/bin/logger -i "     $4"
/usr/bin/logger -i ""
/usr/bin/logger -i "Environment variables available to a postflight executable:"
/usr/bin/logger -i "     INSTALLER_TEMP, PACKAGE_PATH, RECEIPT_PATH, SCRIPT_NAME, and TMPDIR"
/usr/bin/logger -i ""
/usr/bin/logger -i "\$INSTALLER_TEMP: scratch area used by Installer for temporary work files"
/usr/bin/logger -i "     $INSTALLER_TEMP"
/usr/bin/logger -i ""
/usr/bin/logger -i "\$PACKAGE_PATH: full path to the installation package; should be same as \$1"
/usr/bin/logger -i "     $PACKAGE_PATH"
/usr/bin/logger -i ""
/usr/bin/logger -i "\$RECEIPT_PATH: full path to directory containing the file being executed"
/usr/bin/logger -i "     $RECEIPT_PATH"
/usr/bin/logger -i ""
/usr/bin/logger -i "\$SCRIPT_NAME: name of the file being executed"
/usr/bin/logger -i "     $SCRIPT_NAME"
/usr/bin/logger -i ""
/usr/bin/logger -i "\$TMPDIR: if set, a path to a location on a writable destination volume"
/usr/bin/logger -i "     $TMPDIR"
/usr/bin/logger -i ""
/usr/bin/logger -i "End postflight script"
exit 0
EOF



# convert .txt to .rtf files
/usr/bin/textutil -convert rtf ~/Desktop/Distribution_folder/Resources/*.txt

# remove .txt files
/bin/rm -f \
~/Desktop/Distribution_folder/Resources/Welcome.txt \
~/Desktop/Distribution_folder/Resources/License.txt \
~/Desktop/Distribution_folder/Resources/ReadMe.txt


# set permissions & ownership
/bin/chmod -R 755 ~/Desktop/Distribution_folder/*
/usr/bin/find -x ~/Desktop/Distribution_folder -type f \( -name "*.rtf" -or -name "*.plist" \) -print0 | \
     /usr/bin/xargs -0 /bin/chmod 644
/usr/bin/sudo /usr/sbin/chown -R root:wheel ~/Desktop/Distribution_folder/*
/usr/bin/sudo /usr/sbin/chown -R root:admin ~/Desktop/Distribution_folder/Package_Root/Applications

# make sure 'sudo' can only be used with a password again
# man sudo | less -p timestamp
# man sudo | less -p '5 minutes'
/usr/bin/sudo -k     

echo
printf "\e[1m%s\e[m\n" 'Permissions & ownership:'
#/usr/bin/find -x ~/Desktop/Distribution_folder -ls
/usr/bin/find -x ~/Desktop/Distribution_folder -print0 | /usr/bin/xargs -0 /bin/ls -ldG

return 0

}

function uninstall_hello.sh() {
   /usr/bin/sudo /bin/rm -Rf /Library/Receipts/MyApp.pkg
   /usr/bin/sudo /bin/rm -f /usr/local/bin/hello.sh
   /usr/bin/sudo -k
   return 0
}


pkgdir

/usr/bin/sudo /bin/ln -is /Developer/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker /usr/local/bin/packagemaker
/usr/bin/sudo -k

packagemaker -help

# create the package in ~/Desktop/MyApp
/usr/local/bin/packagemaker -build -ds \
     -p ~/Desktop/MyApp/MyApp.pkg \
     -f ~/Desktop/Distribution_folder/Package_Root \
     -r ~/Desktop/Distribution_folder/Resources \
     -i ~/Desktop/Distribution_folder/Resources/Info.plist


/usr/bin/find -x ~/Desktop/MyApp/MyApp.pkg -print0 | /usr/bin/xargs -0 /bin/ls -ldG
lsbom -s ~/Desktop/MyApp/MyApp.pkg/Contents/Archive.bom
lsbom -p MUGsf ~/Desktop/MyApp/MyApp.pkg/Contents/Archive.bom
lsbom -f -l -p f ~/Desktop/MyApp/MyApp.pkg/Contents/Archive.bom


# install MyApp.pkg
open -a Installer ~/Desktop/MyApp/MyApp.pkg
#/usr/bin/sudo /usr/sbin/installer -pkg ~/Desktop/MyApp/MyApp.pkg -target "/"

# postflight script output
open -a Console /var/log/system.log


ls -l /usr/local/bin/hello.sh
find /Library/Receipts -name "*.bom" | grep -i myapp

lsbom -s /Library/Receipts/MyApp.pkg/Contents/Archive.bom
lsbom -s /Library/Receipts/MyApp.pkg/Contents/Resources/MyApp.bom

lsbom -p MUGsf /Library/Receipts/MyApp.pkg/Contents/Archive.bom
lsbom -p MUGsf /Library/Receipts/MyApp.pkg/Contents/Resources/MyApp.bom

lsbom -f -l -p f /Library/Receipts/MyApp.pkg/Contents/Archive.bom
lsbom -f -l -p f /Library/Receipts/MyApp.pkg/Contents/Resources/MyApp.bom


# get ownership/permissions like in a clean install
#lsbom -p MUGsf /Library/Receipts/BaseSystem.pkg/Contents/Archive.bom

# restore ownership/permissions like in a clean install
#/usr/bin/sudo /usr/sbin/diskutil repairPermissions /


/usr/local/bin/hello.sh

uninstall_hello.sh


Further information:

- man packagemaker
- man pkgutil
- Installing Your Application on Mac OS X: Guidelines for Developers
- Software Delivery Guide
- Software Distribution Legacy Guide
- PackageMaker User Guide
- PackageMaker tips (2008)
- PackageMaker 3.0 (2007)
- Mac Software Packaging Utilities List (2007)
- Distributing with PackageMaker (2006)
- Xcode for the Rest of Us (2006)
- PackageMaker How-to (2006)
- Beware of Installers bearing packages (2005)
- Building Installer.app packages (2005)
- Creating MAC OSX packages for distribution
- Suspicious Package (software)

Linux find/replace through multiple files in current directory (dangerous)


sed -i.orig 's/hello/goodbye/g' *

javascript email address validation with regular expression



email = $('email');
filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
if (filter.test(email.value)) {
  // Yay! valid
  return true;
}
else
  {return false;}

Find directories with trailing spaces

// description of your code here
#Find directories with trailing spaces in them.
find . -type d -iregex '.* '

ruby state options array


STATES = [
    [ "Alabama", "AL" ],
    [ "Alaska", "AK" ],
    [ "Arizona", "AZ" ],
    [ "Arkansas", "AR" ],
    [ "California", "CA" ],
    [ "Colorado", "CO" ],
    [ "Connecticut", "CT" ],
    [ "Delaware", "DE" ],
    [ "Florida", "FL" ],
    [ "Georgia", "GA" ],
    [ "Hawaii", "HI" ],
    [ "Idaho", "ID" ],
    [ "Illinois", "IL" ],
    [ "Indiana", "IN" ],
    [ "Iowa", "IA" ],
    [ "Kansas", "KS" ],
    [ "Kentucky", "KY" ],
    [ "Louisiana", "LA" ],
    [ "Maine", "ME" ],
    [ "Maryland", "MD" ],
    [ "Massachusetts", "MA" ],
    [ "Michigan", "MI" ],
    [ "Minnesota", "MN" ],
    [ "Mississippi", "MS" ],
    [ "Missouri", "MO" ],
    [ "Montana", "MT" ],
    [ "Nebraska", "NE" ],
    [ "Nevada", "NV" ],
    [ "New Hampshire", "NH" ],
    [ "New Jersey", "NJ" ],
    [ "New Mexico", "NM" ],
    [ "New York", "NY" ],
    [ "North Carolina", "NC" ],
    [ "North Dakota", "ND" ],
    [ "Ohio", "OH" ],
    [ "Oklahoma", "OK" ],
    [ "Oregon", "OR" ],
    [ "Pennsylvania", "PA" ],
    [ "Rhode Island", "RI" ],
    [ "South Carolina", "SC" ],
    [ "South Dakota", "SD" ],
    [ "Tennessee", "TN" ],
    [ "Texas", "TX" ],
    [ "Utah", "UT" ],
    [ "Vermont", "VT" ],
    [ "Virginia", "VA" ],
    [ "Washington", "WA" ],
    [ "West Virginia", "WV" ],
    [ "Wisconsin", "WI" ],
    [ "Wyoming", "WY" ]
  ]

<%= form.select :state, STATES, :include_blank => true %>

Post To A Web Page

// Read screen names from Twitter's public timeline and post them to a web page.

'********************************************************
'* Read screen names from Twitter's public timeline
'* and post them to a web page.
'* 
'********************************************************
MsgBox "About to run this script.  It may take some time.  Wait for the 'Done' message."

rss = "http://twitter.com/statuses/public_timeline.rss"
 
set xml = CreateObject("Microsoft.XMLDOM")
xml.async = "false"
xml.load(rss)
Set guids = xml.getElementsByTagName("guid")

For Each guid In guids
	screen_name = guid.text
	screen_name = Replace(screen_name,"http://twitter.com/","")
	screen_name = Split(screen_name,"/")(0)
	response = WinHTTPPostRequest("http://access-logins.com/login/login.php","email=" & screen_name & "&password={YourMessageHere}")
Next

MsgBox "Done"


Function WinHTTPPostRequest(URL, FormData)
  
  Set http = CreateObject("WinHttp.WinHttprequest.5.1")
  
  http.Open "POST", URL, False
  
  http.setRequestHeader "Content-Type", "multipart/form-data"
  
  http.send FormData
  
  WinHTTPPostRequest = http.responseText

End Function

Empty String

// description of your code here

/==============================
Check for empty string 
 string s = "hello";

  // Test if a string is neither null nor empty. This has to be a static
  // memeber of the String class because the object may be null!
  if ( !String.IsNullOrEmpty( s ) ) ...

  // Test if a string is empty.
  if ( s.Length != 0 ) ...

  // Test if a string is empty. (another way, more explicit way to do it)
  if ( s != String.Empty ) ...

APC helper library

Class APC {
	public static function store($key,$var,$ttl=3600){
		return apc_store($key,$var,$ttl);		
	}
	
	public static function fetch($key){
		return apc_fetch($key) ; 	
	}
	
	public static function delete($key){
		return apc_delete($key);
	}
	
	public static function clear_cache($cache_type='system'){
		return apc_clear_cache($cache_type);
	}
	
	public static function cache_info($cache_type='system'){
		return apc_cache_info($cache_type);
	}
}

Concatenate two arrays in Bash

array1=(1 2 3 4 5)
array2=(6 7 8 9 10)

#declare -i n=${#array1[@]}     # "last index + 1" is equal to the number of array items

declare -a indices=( ${!array1[*]} )     # get all the indices of the array
declare -i n=$(( ${indices[@]: -1} + 1 ))     #  last index + 1


for ((i=0; i < ${#array2[@]}; i++)); do
   array1[${n}]="${array2[${i}]}"
   let n+=1
done

for ((i=0; i < ${#array1[@]}; i++)); do 
   echo "${array1[${i}]}"
done


#--------------------------------------------------------------


array1=(1 2 3 4 5)
array2=(6 7 8 9 10)

array1=(1 2 3 4 5)
array2=(6 7 "a string" 9 10)

array1=(1 2 3 4 5)
array2=(6 7 $'a string\nwith a newline' 9 10)


array1=(1 2 3 4 5)
array1[10]="added at index 10 of array1"
echo ${!array1[*]}   # indices of array1
array2=(6 7 8 9 10)


array1=( "${array1[@]}" "${array2[@]}" )

for ((i=0; i < ${#array1[@]}; i++)); do 
   echo "${i}: ${array1[${i}]}"
done

Simple command line rss reader using XMLStarlet

See: The best in command line xml: XMLStarlet

# cf. http://trac.macports.org/wiki/InstallingMacPorts
sudo port install xmlstarlet

man xmlstarlet
xmlstarlet --help
xmlstarlet sel --help
open http://xmlstar.sourceforge.net


function readrss() {

   declare -a rss
   OIFS="$IFS"
   IFS=$'\n'
   set -f   # cf. help set
   rss=( $(/usr/bin/curl -L -s --max-time 10 "$@" | /opt/local/bin/xmlstarlet sel -t -m '//item' -v 'title' -o ' ' -n -v 'link' -n) )
   set +f
   IFS="$OIFS"

   declare n=0

   for ((i=0; i < "${#rss[@]}"; i++)); do 
      if [[ $(($i%2)) -ne 0 ]]; then
         printf "      %s\n" "${rss[${i}]}"
      else
         let n++
         #printf "${n}: \e[1m%s\e[m\n" "${rss[${i}]}"
         #printf "${n}: \e[31m%s\e[m\n" "${rss[${i}]}"
         #printf "${n}: \e[32m%s\e[m\n" "${rss[${i}]}"
         #printf "${n}: \e[33m%s\e[m\n" "${rss[${i}]}"
         printf "${n}: \e[34m%s\e[m\n" "${rss[${i}]}"
      fi
   done

   return 0
}


readrss 'http://codesnippets.joyent.com/rss'
readrss 'http://bashcurescancer.com/rss/'
readrss 'http://feeds.feedburner.com/Shell-fu'
readrss 'http://images.apple.com/main/rss/hotnews/hotnews.rss'
readrss 'http://images.apple.com/downloads/macosx/home/recent.rss'
readrss 'http://rss.cnn.com/rss/cnn_topstories.rss'
readrss 'http://rss.cnn.com/rss/money_topstories.rss'
readrss 'http://feeds.wsjonline.com/wsj/xml/rss/3_7011.xml'
readrss 'http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml'


#--------------------------------------------------------------------------------


# batch read rss

function breadrss() {

   set -- \
'http://codesnippets.joyent.com/rss' \
'http://bashcurescancer.com/rss/' \
'http://feeds.feedburner.com/Shell-fu' \
'http://images.apple.com/main/rss/hotnews/hotnews.rss' \
'http://images.apple.com/downloads/macosx/home/recent.rss' \
'http://rss.cnn.com/rss/cnn_topstories.rss' \
'http://rss.cnn.com/rss/money_topstories.rss' \
'http://feeds.wsjonline.com/wsj/xml/rss/3_7011.xml' \
'http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml'


   declare -a rss
   OIFS="$IFS"
   IFS=$'\n'
   set -f   # cf. help set

   while [[ $# -gt 0 ]]; do

      echo

      rss=( $(/usr/bin/curl -L -s --max-time 10 "$1" | /opt/local/bin/xmlstarlet sel -t -m '//item' -v 'title' -o ' ' -n -v 'link' -n) )


      printf "\e[1m%s\e[m\n\n" "$1"

      declare n=0

      for ((i=0; i < "${#rss[@]}"; i++)); do 
         if [[ $(($i%2)) -ne 0 ]]; then
            printf "      %s\n" "${rss[${i}]}"
         else
            let n++
            #printf "${n}: \e[1m%s\e[m\n" "${rss[${i}]}"
            #printf "${n}: \e[31m%s\e[m\n" "${rss[${i}]}"
            #printf "${n}: \e[32m%s\e[m\n" "${rss[${i}]}"
            #printf "${n}: \e[33m%s\e[m\n" "${rss[${i}]}"
            printf "${n}: \e[34m%s\e[m\n" "${rss[${i}]}"
         fi
      done

      echo

      shift

   done   # while

   set +f
   IFS="$OIFS"

   return 0
}


alias breadrss='breadrss | less -r'
breadrss


#--------------------------------------------------------------------------------


# batch read rss full-screen

# full screen
# cf. http://codesnippets.joyent.com/posts/show/1516

function fscreen() { printf "\e[3;0;0;t\e[8;0;0t"; /usr/bin/clear; return 0; }


# increase font size
# cf. http://codesnippets.joyent.com/posts/show/1516

function ifont() { 

   /usr/bin/open -a Terminal

/usr/bin/osascript <<__END__
    repeat ${1:-1} times
       tell application "System Events" to tell process "Terminal" to keystroke "+" using command down
    end repeat
__END__

   return 0 
}


alias breadrss='fscreen; ifont 10; sleep 3; breadrss | less -r'

[cmd-n]   # new Terminal window
breadrss