rsync

A while back, I was looking for a command line replacement for FTP. Even with the best FTP app out there, dragging and dropping files can get tedious, especially for little updates that you just want to see on the remote server (yeah, you can sync in Transmit… but you still have to open the app and whatnot).

In review, SFTP is decent if you want to browse around the remote server. SCP is quick and easy for uploading a single file. But if you’re looking to sync-up a whole directory, rsync is the way to go.

Because rsync is such an old utility, I had some trouble finding a decent tutorial or blog post. The best reference is its man. So long as you have SSH access, using rsync is fairly straight forward. To upload:

rsync -avz /local/myproject/ user@server:/remote/myproject

To download:

rsync -avz user@server:/remote/myproject/ /local/myproject/

Looking at the arguments, -a syncs all subdirectories, -z compresses the transfer, and -v makes the procedure verbose.

This would recursively transfer all files from the directory src/bar on the machine foo into the /data/tmp/bar directory on the local machine. The files are transferred in “archive” mode, which ensures that symbolic links, devices, attributes, permissions, ownerships, etc. are preserved in the transfer. Additionally, compression will be used to reduce the size of data portions of the transfer.

Note that the remote path in the download script has a trailing /.

A trailing slash on the source changes this behavior to avoid creating an additional directory level at the destination. You can think of a trailing / on a source as meaning “copy the contents of this directory” as opposed to “copy the directory by name.”

I’m using this command in a couple li’l bash scripts to deploy projects to my remote server. Here’s demo/deploy.sh

#!/bin/bash
rsync -avz --exclude '.git' --exclude '*.sh' ./ $BERNA:~/www/demo

The --exclude argument specifies which files to not sync. For desandro.com/deploy.sh, I use --exclude-from and a separate file exclude.txt. ($BERNA is a local alias I have user@server, so I can keep my username and server semi-private.)

I use this following script, sync.sh, upload and download:

#!/bin/bash

REMOTE=user@server:remote/dir

if [ "$1" == 'down' ]; then
	PATHS="$REMOTE/ ./"
else
	PATHS="./ $REMOTE"
fi

rsync -avz --exclude 'ignoreme.txt' $PATHS

./sync.sh uploads, and ./sync.sh down downloads.

git config --get remote.origin.url

Here’s a faster way to get the URL of a remote git repo, using git config:

git config --get remote.origin.url
# >> git@github.com:desandro/dropshado.ws.git

Or to get list all the options of local .git/config:

git config --local -l
# >> core.repositoryformatversion=0
# >> core.filemode=true
# >> core.bare=false
# >> core.logallrefupdates=true
# >> core.ignorecase=true
# >> remote.origin.url=git@github.com:desandro/dropshado.ws.git
# >> remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
# >> branch.gh-pages.remote=origin
# >> branch.gh-pages.merge=refs/heads/gh-pages

See previous method git remote show origin.

Li'l bash scripts

After coming across Modernizr’s compress bash script, I’ve been adding my own li’l bash scripts here and there in my projects. They help automate any repetitive task, or provide a shortcut for a bash command I don’t want to remember.

Development

Make a sweet bash script, like helloworld.sh:

#!/bin/bash
echo 'Hello world!'

Make the script executable by changing the permissions:

$ chmod 755 helloworld.sh

Run the script from the command line

$ ./helloworld.sh
# > Hello World

Examples

metafizzy.co / newpost.sh and dropshado.ws / newpost.sh: creates a new post from a template

#!/bin/bash

# creates a new post
# format as _posts/YYYY/YYYY-MM-DD-filename.ext
# usage:
#   $ ./newpost.sh my-new-post-filename

COPY_FILE=_posts/template.mdown
# create file
POST_FILE=_posts/$(date "+%Y/%Y-%m-%d")-$1.mdown

echo new post: $POST_FILE
cp $COPY_FILE $POST_FILE
# open it
mate $POST_FILE

demo / deploy.sh and desandro / deploy.sh: rsyncs project to remote server

#!/bin/bash
rsync -avz --exclude '.git' --exclude '*.sh' ./ $BERNA:~/www/demo

neo-vision / build.sh: moves release files into sub directory, compresses JS, zips it all up

#!/bin/bash

BUILD_DIR='neo-vision'
ZIP='neo-vision.zip'
REMOVABLES=("build.sh" "prettify.js" "lang-css.js" "README.mdown" $ZIP)

rm -rf $BUILD_DIR/
mkdir $BUILD_DIR
cp *.* $BUILD_DIR

# minifies prettify js
cat prettify.js lang-css.js | uglifyjs -nc > $BUILD_DIR/prettify.min.js

for REMOVE in "${REMOVABLES[@]}"
do
	rm $BUILD_DIR/$REMOVE
done

zip -r -u $ZIP $BUILD_DIR

GitHub link to source code with commit tree

When referencing source code in a GitHub project, it’s nice to be able to link to specific lines of a source file. GitHub makes this easy enough. From the main project page (github.com/jquery/jquery), you can browse to a specific file (github.com/jquery/jquery/blob/master/src/css.js) and then click on line numbers to highlight a line, which also sets the URL anchor (blob/master/srs/css.js#L171), and Shift+Click to highlight multiple lines (blob/master/srs/css.js#L171-185).

The only problem is that source files are subject to change, or even be removed, so there’s no guarantee that your link will always point to the correct place. By default, GitHub project pages link to the most current version of the source. A better practice is to link to a specific commit, where the content of source files are not subject to versioning.

To view a GitHub project at a certain commit, click on the tree link in the commit header, or just press t on your keyboard. You can then browse the project files, and link to sources of this commit, i.e. github.com/jquery/jquery/blob/27291ff06ddb655f90a8d1eada71f7ac61499b12/src/css.js#L171-185. Note that the only difference in the URL is changing the branch name master with the commit SHA.

+1 tip from Paul Irish:

plus you only need 4 characters of the SHA in the URL.. it figures it out. i usually truncate to 7ish characters.

Nice: github.com/jquery/jquery/blob/27291ff/src/css.js#L171-185

Re-enable Option+arrow move-by-word in Lion

Before you go whining like an impulsive brat about a reliable OS X feature that you believe has been sorely ripped out of Lion, rest assure that there’s probably a preference setting for it.

In my case, my beloved Opt+arrow move-by-word key bindings were not working after I upgraded to Lion. Turns out the default keyboard shortcuts for Mission Control were conflicting with them. Go to System Preferences » Keyboard » Keyboard Shortcuts and disable or change Mission Control: Move left/right a space.

Lion Keyboard Shortcuts Preferences

Sorry about that :P

.gitconfig colors

Aw yeah, another command-line coloring post!

John Schulz pointed me to this git cheat sheat. Right up front it provides the settings in ~/.gitconfig to color git command output like git diff, git status, and git branch. Here’s what I’m rocking:

[core]
  quotepath = false
  whitespace=fix,-indent-with-non-tab,trailing-space,cr-at-eol
[color]
  ui = true
[color "branch"]
  current = yellow black
  local = yellow
  remote = magenta
[color "diff"]
  meta = yellow bold
  frag = magenta bold
  old = red reverse
  new = green reverse
  whitespace = white reverse
[color "status"]
  added = yellow
  changed = green
  untracked = cyan reverse
  branch = magenta

Which looks like:

color git commands

Option + Click to download link source in Chrome

Option + Click on a link in Google Chrome to download the source of the linked page.

Chrome source files

Looking under the hood at the Chrome dev tools and user agent styles, I came across some of the source files that power the dev tools

devTools.css is worth taking a look a look at as it has the base styles for the syntax highlighting used in the dev tools. Search for /* inspectorSyntaxHighlight.css */.

If you’re interested in taking a peek, I’d point you to resources.pak located in /Applications/Google Chrome/Contents/YOUR_VERSION/Google Chrome Framework.framework/Resources/resources.pak.

Coloring remote command line prompts

Picking up on a running theme on the dropshado.ws, I gots to have my command line prompts looking fresh. Locally, I’m now using bash-it, with its killer theming engine by John Schulz to make it happen.

Just recently I realized that I can style my prompt on my remote server when I SSH. Here’s what I added to ~/.bash_profile.

PS1="\[\e[0;32m\]\u@\h \[\e[0;34m\]\w \[\e[0;30m\]# \[\e[39m\]"

Which looks like

username@server ~/path/to/dir # writing sweet commands

Inspecting DOM object properties

I like taking a peek at native DOM objects like Element and Node using the console’s dir function.

dir( Element )

Then I crack open prototype see all the base properties and methods that native constructor has.

Element prototype

I discovered Element.contains() this way.

Returning to stop the function

I’ve been using return more to stop logic inside a function. See PPK: Returning to stop the function.

// within conditional
function doStuff() {
  var myCondition = checkCondition();
  if ( !myCondition ) {
    // do
    // lots
    // of
    // stuff
  }
}

// proceed if condition is met
function doStuff() {
  var myCondition = checkCondition();
  // don't proceed if not myCondition
  if ( !myCondition ) {
    return;
  }
  // do
  // lots
  // of
  // stuff
}

The benefit is that the subsequent code isn’t all held within the conditional, thus breaking it out of an unnecessary nest… like an newborn eagle on its first flight.

jQuery version in jQuery.fn.jquery

Get the version of jQuery

jQuery.fn.jquery
// >> '1.6.1'

It’s bizarre that you can get this via a jQuery method. It allows you to get it as a property on any jQuery object.

$(document).jquery
// >> '1.6.1'