Make tab-completion in bash case-insensitive

I added this to a discussion on the MacAdmins Slack today and realized it could be useful for a broader audience.

The underlying problem is that by default HFS+ (the file system of OS X) is “case preserving, but case-insensitive.” That means the file system will remember wether you named a file or directory “README.TXT” “ReadMe.txt” or “readme.TXT” and preserve that case, but using either of these will point to the same file.

This may be confusing in Terminal. Since most other Unix and Linux file-system are case-sensitive (i.e. README.TXT and readme.txt are different files) most shells are, too. So on OS X in bash you can write:

$ cd ~/DESKTOP

and it will actually work. Though if you then print the working directory, you get

$ pwd
/Users/armin/DESKTOP

which doesn’t hurt anything really, since Desktop and DESKTOP are the same. But it does hurt our OCD, right?

While I have not yet found a way to change this behaviour directly, one thing you can change is wether tab-completion is case-sensitive or not. Since the underlying filesystem is insensitive, there really is no reason tab-completion should be. This way you can type /sy[tab]/l[tab]/cor[tab] and it will expand to /System/Library/CoreServices/.

Tab-completion is not just for laziness, but also a way to ensure you are typing a path correctly, especially since tab-completion will escape spaces and other nasty characters automatically.

To make tab-completion in bash case-insensitive put this in your .inputrc (create if necessary)

# Ignore case while completing
set completion-ignore-case on

and then close all Terminal windows and start a new one.

quickpkg update

I updated quickpkg with a few additions:

Scripts

You can now add pre- and postinstall scripts or an entire folder of scripts.

Ownership

Added an --ownership parameter that will be passed straight through to pkgbuild. Usually the default recommended will be what you want, but it is there if you need it.

Output

There is now a --output parameter that gives you more control over the location and name of the resulting package.

Bonus Trick

And as a neat trick, you can easily create a droplet for quickpkg with Automator by following the same instructions as for munkiimport in this article.

Control Apple Remote Desktop Access with Munki

Previously, I posted how to ensure SSH access is enabled with Munki. Another favored (though sorely neglected by Apple) tool to remote control Macs is obviously Apple Remote Desktop.

Note: Apple Remote Desktop access is called ‘Remote Management’ in the Sharing Preference Pane. This also includes access for the Screen Sharing application.

We will use a nopkg setup to control, so we need one script to check wether the configuration needs to be fixed (ard_installcheck.sh) and a postinstall script to actually do the fixing (ard_postinstall.sh).

The install check script first tests wether ardagent process is running, wether the “All Users” access option is turned on, and finally wether our user for remote access (clientadmin in this example, modify for your needs) is in the privileged group.

Paradoxically, the installcheck has to return 1 when everything is ok. (The actuall install does not have to run so the install is aborted.) If any of the settings aren’t as they should be the script returns 0 (installation needs to proceed) and Munki will run the postinstall script.

The postinstall script uses the kickstart tool to setup ARD the way we want it. (In this example we enable access for two admin accounts clientadmin and localadmin, modify to what you need.)

The run makepkginfo to build the pkginfo which tells Munki what to do:

makepkginfo --name=EnableARD \
    --displayname="Enable Apple Remote Desktop" \
    --pkgvers=1.0 \
    --nopkg \
    --installcheck_script=ard_installcheck.sh \
    --postinstall_script=ard_postinstall.sh \
    --unattended-install > EnableARD.pkginfo

(ard_installcheck.sh and ard_postinstall.sh need to be in the current working directory, or give the path to the scripts.)

Then copy the pkginfo file to the pkginfo folder on the munki repository (or a subfolder), add EnableARD to a manifest and run makecatalogs.

Run managedsoftwareupdate on a client that has that manifest configured.

Even if a user changes the “Remote Management” setting, the next time Munki runs in the background it should notice the change and set them back with the postinstall script.

Introducing `quickpkg`

This tool will quickly and easily build a package from an installed application, a disk image file or zip archive with an enclosed application bundle. It will also extract the application name and version and use it to name the resulting pkg file.

The tool will look for applications on the first level of the disk image or archive. If it finds no or more than one application it will error.

The name of the resulting package will be of the form {name}-{version}.pkg. Spaces will be removed from the name. The package will be written to the current working directory.

Get the tool at the quickpkg repository.

Examples

Build package from installed application:

quickpkg /Applications/Numbers.app

Build package from a disk image:

quickpkg ~/Downloads/Firefox\ 43.0.4.dmg

Build package from a zip archive:

quickpkg ~/Downloads/Things.zip

Background

OS X has had the pkgbuild tool since Xcode 3.2 on Snow Leopard. With pkgbuild you can directly build a installer package from an application in the /Applications folder:

pkgbuild --component /Applications/Numbers.app Numbers.pkg

Or even an application inside a mounted dmg:

pkgbuild --component /Volumes/Firefox/Firefox.app \
         --install-location /Applications \
         Firefox.pkg

This tool even does the work of determining a bundle’s identifier and version and sets the identifier and version of the pkg to the same values.

However, while pkgbuild does automatically name the package, it does not include the version, which is important when you tracking many versions of the same application. It also doesn’t automatically look into a dmg file or zip archive.

quickpkg vs autopkg

This tool is not meant to replace autopkg. autopkg will automate the download, the re-packaging (if necessary) and the upload to and configuration of your client management system. It can also handle much more complex setups than quickpkg. autopkg is far superior and should be your tool of choice.

However, there are situations where autopkg does not work well. The most common reason is if the download cannot be automated because the download page is behind a paywall. Also autopkg requires a recipe for a given piece of software. If no recipe exists, quickpkg may be a simple alternative. (Though if quickpkg works, creating an autopkg recipe should not be hard.)

Warning

All quickpkg does is identify an application bundle and package it in a way that the package will install that application bundle into the /Applications folder. If the application needs other files (libraries, frameworks, configuration files, license files, preferences etc.) to run and work they are your responsibility.

Creating a Droplet for munkiimport

You can use Automator to build an applet for munkiimport. Then you can just drag and drop pkgs, dmgs and Applications on it to import them.

However, can’t just use do shell script since munkiimport will prompt for some extra information. Instead you can use Terminal’s command do script. While do shell script will execute then given command quietly in the background, do script will open a new Terminal window and run the given command – just what we need.

Open Automator and create a new workflow. Choose ‘Application’ as the template. This template will accept files and folders dropped on it. Add a ‘Run AppleScript’ action and fill in the following code:

on run {input, parameters}
  repeat with x in input
    tell application "Terminal"
      do script "munkiimport" & space & quoted form of POSIX path of (x as alias)
    end tell
  end repeat
  return input
end run

Then save the Automator applet as ‘MunkImport’. (or whatever suites you)

The downside of do script versus do shell script is that you cannot receive and process the result.

Copy all Safari tabs to Notes.app

I had previously posted about one of my oldest but still frequently used scripts which gathers all tabs from a window into a text list to be pasted in an email or something like that.

I have recently adapted that script to do something new. This new script will gather the tabs in the frontmost Safari window and create a note in the Notes app with all the links (then, presumably, you would want to clean out and close most of the tabs)

Also I learned that the Safari tabs from all your Macs and iOS devices are stored in the `~/Library/SyncedPreferences/com.apple.Safari.plist` and extended the script to read that instead of grabbing them directly from Safari:

To use it is probably easiest to enable the Script menu (in Script Editor > Preferences) and drop the scripts in the `~/Library/Scripts/Applications/Safari` folder.