Skip to content

Terminal

Living the bifurcated life in macOS Catalina

If you're a macOS Catalina user, and a user of Terminal for various tasks, you might be surprised at how some things work—or rather, don't work, in Catalina. As a first example, consider the Utilities folder…on the left is how it appears in Finder, and on the right, the contents of that same folder listed in Terminal:

While Finder shows a full Utilities folder, Terminal shows it as empty. Why? If you're somewhat familiar with the technical side of macOS Catalina, you probably know the answer: Apple has separated much of the OS and placed it on a read-only volume.

Apple's "About the read-only system volume in macOS Catalina" page explains things fairly well—basically, what you see as one Utilities folder in Finder is really two things: A read-only Utilities folder, and a user-writable Utilities folder. (If my machine had any user-installed apps in the Utilities folder, they would have shown up in the Terminal output above.)

[continue reading…]



See exactly when an app launched

Update: I guess I should have searched here before I posted this—I wrote up another solution a few years ago, and that one includes a Keyboard Maestro implementation. Whoops! As this one's another method, though, I'll leave it up.

I was working on some stuff for our upcoming Usher 2 release, and needed to know how long Usher had been running. A quick web search found this post, where one of the comments had an answer that works well in macOS:

ps -p pid -o lstart=

Replace pid with the process ID (PID) from ps -ax for the app or process in question, and you're done. But it's possible to make it even easier to use by automating the task of getting the process ID. Here's what I came up with:

ps -p `ps ax | grep [U]sher$ | cut -c 1-5` -o lstart=

The bit between the backticks gets the matching process line from ps, then uses cut to keep just the first five columns, which contain the PID.1When the shell encounters backticks, it processes the commands within those backticks before processing the rest of the command—in this case, the backticked command returns the PID.

[continue reading…]



Quickly create a nested folder structure via Terminal

Have you ever needed to create an empty folder structure with many levels of repetitively-named folders? This doesn't happen a lot, obviously, but if you try using Finder for this task, you'll quickly discover it's really tedious. But a quick trip to Terminal makes the task very fast, and it's not overly complicated.

Let's say you need a folder structure to handle reports that you'll be receiving weekly, but need to keep track of over both quarters and years. One way to handle that would be with a folder structure like this:

(Hopefully obviously, the same structure repeats within each separate year's folder.) Creating that many multi-leveled folders in Finder would be time consuming and tedious. But in Terminal, you can create the entire structure with just one command:

mkdir -p 202{0..5}/qtr{1..4}/week{1..13}

That command takes under a second on my iMac to create the entire directory structure (over 330 folders). Zoom! So how does this work?

[continue reading…]



Remove the macOS Catalina guilt trip from macOS Mojave

May 26 2020 Update: The 2020-003 Security Update for Mojave will reset the red flag (and deprecate the command used to ignore the update). However, these steps do still work, so you just have to repeat Miles' solution again. And after you do, do not open the Software Update panel, or the red badge will return. (But if it does, just run the commands yet again.)

May 9 2020 Update: Commenter Miles Wolbe has come up with a much better solution. Ignore everything in this tip, and just run this Terminal command:

sudo softwareupdate --ignore "macOS Catalina" && defaults delete com.apple.preferences.softwareupdate LatestMajorOSSeenByUserBundleIdentifier && softwareupdate --list

If you're interested in why this works, Miles explains it in more detail. I've tested this method, and it works—no more agent required!

I have no plans to move my main iMac to macOS Catalina, at least for the forseeable future. There are two key apps I use—Fujitsu's ScanSnap scanner software and the Many Tricks' accounting app—that are both 32-bit. In addition, there are changes in Catalina relative to permissions that make it somewhat Vista like and slow down my interaction with the system. (My MacBook Air is my "production" Catalina Mac, and I have an older retina MacBook Pro that I use for Catalina betas.)

But Apple really wants people to update to Catalina, so they let you know about Catalina…constantly, it seems. In System Preferences > Software Update, you'll see this…

[continue reading…]



How to auto-crop huge images with ImageMagick

In my recent post A new set of Hubble deep space iMac retina desktops, I included a set of auto-cropped 5120x2880 desktops. In that post, I wrote:

These images were automatically cropped from the master image (after I cropped that; more detail on what I did is coming in a follow-up post), via ImageMagick.

So this would be that post: How to auto-crop huge images using ImageMagick. If you're not familiar with it, ImageMagick is a set of command-line tools to manipulate images. There are a number of ways to install ImageMagick, but I used Homebrew (brew install imagemagick).

[continue reading…]



2019 iMac vs Late 2014 iMac—Ripping addendum

In Part 1 of my 2014 vs 2019 iMac comparison articles, I provided an overview and a number of comparison benchmark results. In Part 2, I looked at changes in gaming performance between the two machines.

But there was one more thing I wanted to do: Compare Blu-ray ripping speeds. At the time, though, I didn't have any new movies to rip, and I really didn't want to spend the time re-ripping an existing movie. Now, though, I do have a few new movies to rip, as I'm trying to finish our collection of all the films in the first three phases (now called the Infinity Saga) of the Marvel Cinematic Universe.

That meant buying the films I'd liked the least—The Incredible Hulk and the first two Thor movies. With that came the chance to compare the Blu-ray ripping speed of the two iMacs. I use the method described in my article Revisiting ripping Blu-ray discs, which is this:

  1. Use MakeMKV to create an MKV file on the hard drive that contains the video and audio tracks.
  2. Use Don Melton's Video Transcoding tools to create the final movie from the MKV file.

Using The Incredible Hulk, I timed how long it took to create the MKV file and how long it took to create the finished movie. Without further ado, the results (times are in hh:mm:ss format)…

[continue reading…]



Using command-line Quick Look as a memory aid

I recently reviewed my new third-party mouse, the Logitech MX Master 2s ($70 at Amazon). I love all the customizable buttons on this mouse, and in particular, the ability to create gestures (which are simply a directional drag while holding down a button).

I've used two buttons to create a total of 10 gesture actions on my mouse:

I created the above image from the Logitech Options app, so I can refer to it if I forget which action I've assigned to which gesture. But it's a pain to find the folder on the disk and open it just to see the image. Then I remembered I had an unused button on my mouse1The upper button of the two near the side scroll wheel

Note: While the following is specific to my Logitech mouse in terms of implementation, read on if you're curious about how to access QuickLook previews from Terminal and/or via a simple AppleScript.

[continue reading…]



Easily see any app’s bundle identifier

I occasionally need to help one of our customers get the bundle identifier for a given app, for some purpose with one of our apps. While the task isn't complicated—the value is stored in a file named Info.plist within each app bundle—it's not something that's necessarily easy to explain to someone who doesn't have a lot of Mac experience.

I figured there must be a less-complicated solution, and I was right, though it's probably higher on the geek factor. After some searching, I found this thread at Super User, which offers a number of solutions. The simplest—and always working, in my experience—was the very first one: Open Terminal and run this command:

osascript -e 'id of app "Name of App"'

The "Name of App" is replaced with the name of the app as it appears when hovering over its Dock icon. For Excel, for example, it'd be:

osascript -e 'id of app "Microsoft Excel"'

Run that command, and it returns com.microsoft.Excel, which is just what I need—I just have the customer copy the output and email it back to me.



View app-specific log messages in Terminal

March 29 2018 Update:

When this tip was first posted, it didn't work right: The log command ignored the --start, --end, and --last parameters. Regardless of what you listed for parameters, you'd always get the entire contents of the log file. I'm happy to note that this has been resolved in macOS 10.13.4, as log now functions as expected:

$ log show --last 20s --predicate 'processImagePath CONTAINS[c] "Twitter"'
Filtering the log data using "processImagePath CONTAINS[c] "Twitter""
Skipping info and debug messages, pass --info and/or --debug to include.
Timestamp                       Thread     Type        Activity             PID    TTL  
2018-03-30 09:26:15.357714-0700 0xc88a8    Default     0x0                  5075   0    Twitterrific: (CFNetwork) Task <9AD0920A-7AE7-4313-A727-6D34F4BBE38F>.<250> now using Connection 142
2018-03-30 09:26:15.357742-0700 0xc8d7a    Default     0x0                  5075   0    Twitterrific: (CFNetwork) Task <9AD0920A-7AE7-4313-A727-6D34F4BBE38F>.<250> sent request, body N
2018-03-30 09:26:15.420242-0700 0xc88a8    Default     0x0                  5075   0    Twitterrific: (CFNetwork) Task <9AD0920A-7AE7-4313-A727-6D34F4BBE38F>.<250> received response, status 200 content K
2018-03-30 09:26:15.420406-0700 0xc8d7a    Default     0x0                  5075   0    Twitterrific: (CFNetwork) Task <9AD0920A-7AE7-4313-A727-6D34F4BBE38F>.<250> response ended
 --------------------------------------------------------------------------------------------------------------------
Log      - Default:          4, Info:                0, Debug:             0, Error:          0, Fault:          0
Activity - Create:           0, Transition:          0, Actions:           0
$

This makes it really easy to get just the time slice you need from the overly-long log files. You can use s for seconds, m for minutes, h for hours, and d for days as arguments to these parameters.

This article provides a nice overview on interacting with log and predicates to filter the output—there's a lot you can do to help figure out what might be causing a problem.

And now, here's the rest of the original post…

[continue reading…]



See how long an app has been running

For a recent customer support question, I needed to know how long our app Witch had been running. There are probably many ways to find this out, but I couldn't think of one. A quick web search found the solution, via ps and the etime flag.

You need the process ID (pid), which you can find via ps ax | grep [a]ppname.1That [s]quare brackets around the first letter are there so grep won't find itself—and thus list itself in the output. In my case, Witch runs a background task called witchdaemon, so I did it this way…

$ ps -ax | grep [w]itchd
  774 ??        26:40.73 /Users/robg/Library/PreferencePanes...[trimmed]

With the pid, the command to find that process' uptime is:

$ ps -o etime= -p "774"
11-03:17:12

The elapsed time readout is in the form of dd-hh:mm:ss, so Witch had been running for 11 days and a few hours and minutes. Note that you can combine these steps, getting the process ID and using it in the ps command all at once:

ps -o etime= -p "`ps -ax | grep [a]ppname | cut -d ' ' -f 1`"

It's messy looking, but this form saves time and typing.

June 2018 Addendum: If you add the lstart flag, you can see the exact start date and time for the process. For example:

$ ps -o lstart= -o etime= -p "16866"
Tue Jun  5 05:49:19 2018     09-06:11:25