Changing the measure
August 17, 2025 at 2:49 PM by Dr. Drang
Something Kieran Healy wrote several years ago has stuck with me: If you want to measure change, you can’t change the measure. Kieran attributes that pithy bit of advice to Tom Smith of the General Social Survey, but my Google and Kagi searches always lead to Kieran. Regardless, it’s good to keep in mind.
For example, here’s the past month or so of my resting heart rate according to Apple’s Health app:
Not much change from day to day. But if I look at a graph of last year, I see a big drop from June to July:
What happened? A new medication maybe? No. July 2024 is when I started wearing my watch overnight and either
- the watch’s heuristics say I’m awake and resting when I’m really asleep; or
- because I’m wearing the watch in bed, it’s measuring my heart rate when I’m awake but more rested than I am during the day.
Whichever of these is correct, what’s not correct is that my heart rate suddenly dropped about five beats per minute last year.
I thought about this during the recent dustup over the Bureau of Labor Statistics’ employment figures. One way to make future numbers look better for the Trump administration would be to alter the method used to convert the raw data into the reported figures—to change the measure. This would make comparisons with the old jobs numbers illegitimate, but that wouldn’t stop Trump from doing it.
But coming up with a new method of calculation sounds like a lot of work, and a calculation that gives favorable results now might give unfavorable results a few months from now. Perhaps that’s why E.J. Antoni has floated the idea of suspending the monthly jobs reports. This would introduce a new principle: If you don’t want to measure change, do nothing.
Updated library searching
August 16, 2025 at 4:24 PM by Dr. Drang
After a couple of months of using my library search web page, I decided it needed a small upgrade, which I added today. It’s a new button that resets the search form.
The page used to look like this on my phone before and after a search:
This was fine for a single search, but when I did two or more searches in a row, I had to delete the entry fields before typing in new search terms. This wasn’t the worst thing in the world, but I decided it would be nicer to have a Reset button that deleted the search fields with a single tap. It now looks like this:
Tapping the Reset button after a search returns it to the state on the left.
There wasn’t much to change. The Python CGI script that builds the page now has this section of code,
python:
# Output HTML
print(f'''Content-Type: text/html
<html>
<head>
<title>Library Search</title>
<link rel="stylesheet" href="search.css">
</head>
<body>
<h1>Library Search</h1>
<form method="get" action="search.py">
<p class="desc">Enter strings for title, author, or both</p>
<label for="title">Title:</label>
<input type="text" name="title" value="{tString}">
<label for="author">Author:</label>
<input type="text" name="author" value="{aString}">
<input type="submit" value="Submit">
<a id="reset" href="search.py">Reset</a>
</form>
<div class="results">
<h2>{rheader}</h2>''')
where the addition is this pair of lines of HTML to the print
call:
xml:
<a id="reset" href="search.py">Reset</a>
I’ve basically just added a link that reloads the CGI script with no parameters. To get the link to look like a button, I added two short sections to the CSS. One in the default area,
css:
form a[id="reset"] {
padding: .6em 1.5em;
border: none;
border-radius: 4px;
color: #000;
background-color: #ddd;
text-decoration: none;
}
which affects the page when I look at in on my computer, and another in the @media (pointer: coarse)
area,
css:
form input[type="submit"] {
padding: .6em 3.25em;
margin-top: 0.5em;
}
form a[id="reset"] {
padding: .6em 3.5em;
margin-top: 0.5em;
}
which affects the page when I look at it on my phone. In addition to styling the Reset button, this shrinks the Submit button so they both fit on the same line.
The full Python and CSS code is back on the original post.
Enclosing folders via zsh modifiers
August 15, 2025 at 5:36 PM by Dr. Drang
I don’t want to give you the impression that I get all my blogging ideas from Jason Snell, but here’s the second one this week. It was inspired by his post this morning about using the new folder automation feature in macOS 26. After bookmarking the article so I can refer to it after upgrading to 26, I started thinking about how he and Dan Moren went about extracting the name of a file’s enclosing folder from its full path name.
They went about it in basically the same way: splitting the Unix path string on slash characters. The difference was that while Dan was happy to get the full path to the enclosing folder, Jason wanted just the enclosing folder’s name. For example, for a file named
/Users/jsnell/Desktop/Drop It Here/Markdown File.md
Dan wanted
/Users/jsnell/Desktop/Drop It Here
whereas Jason wanted
Drop It Here
Their solutions were Shortcuts-native, by which I mean they used Shortcuts actions only—no “outside” calls to AppleScript or the shell or any other scripting language. But I immediately thought of using the shell’s dirname
and basename
commands to replace their and actions.
It wasn’t hard to do, but I thought it was clumsy because dirname
and basename
don’t use standard input, so I couldn’t just pipe the output of one to the other. (dirname
by itself would give me Dan’s solution, but I wanted to make my life harder by replicating Jason’s solution.)
A cleaner approach came from zsh
’s modifiers, suffixes you can append to pull out parts of a file path. Recent versions of bash
also have modifiers, but not the old version that Apple supplies with macOS.
Because I’m not running macOS 26, I couldn’t build a folder automation Shortcut, but here’s a proof-of-concept Shortcut named
that runs as a Quick Action on selected files in the Finder.For each selected file, the full path is passed as the argument to this script,
echo ${1:h:t}
and the output is displayed in a window.
$1
is the first (and only) argument to the script. The :h
modifier pulls out the “head” of the path, which is the path to the enclosing folder. The :t
modifier returns the “tail” of that, which is just the name of the enclosing folder. Brace expansion isn’t necessary in this case, but I tend to use it when doing anything more complicated than just referencing a variable.
As you can see in the Shortcuts sidebar, this is saved as a Quick Action that’s meant to be invoked from the context menu in the Finder.
To test it, I added a Drop It Here
folder to my Desktop and put two files in it: Markdown File.md
and Another Markdown File.md
. Note that I’ve included spaces in both the file names and the folder name to see whether that screws up the shell script. Here’s me calling the Quick Action from the context menu,
and here’s the window that appears twice, once for each of the selected files,
So it works. And if I’d wanted to replicate Dan’s approach, I would’ve used just
echo ${1:h}
in the shell script.
This is not an improvement on Jason’s or Dan’s work. I wouldn’t disagree if you said it was worse than their Shortcuts because it’s more cryptic. Far more people know that directories are separated by slashes than know about :h
and :t
. But it was fun to reacquaint myself with modifiers.
Blood oxygen
August 14, 2025 at 8:34 PM by Dr. Drang
Nobody comes here for Apple news, so I assume you’ve already heard that Apple has started activating the blood oxygen sensor on all Apple Watches with the sensor. Until today, watches sold in the United States after January 2024 had their sensors deactivated because of the Masimo patent. As mentioned in the linked press release, new versions of watchOS (11.6.1) and iOS (18.6.1) will work together to let you take readings on your watch and then calculate and display the blood oxygen level on your phone. I have some thoughts.
First, I agree with Warner Crocker that this new US Customs ruling smells like the shit Tim Cook ate last week in the White House. Warner made the point less crudely.
Next, because I bought my Series 9 Watch in the fall of 2023, before the earlier Customs ruling went into effect, I’ve always had the blood oxygen sensor active. So I read this part of the press release very carefully:
There will be no impact [from the OS updates] to Apple Watch units previously purchased that include the original Blood Oxygen feature, nor to Apple Watch units purchased outside of the U.S.
That’s nice to hear, but I’m going to wait a bit before updating to see if the “no impact” promise matches reality. I feel bad that my trust in Apple software has fallen this far, but that’s how it is.
Finally, I’ve often wondered about the difference in Apple’s treatment of the blood oxygen and temperature sensors. By default, you don’t get an actual temperature reading; instead you get a variation from your “baseline” temperature. And Apple is careful to call it “Wrist Temperature” instead of just “Temperature,” presumably because it doesn’t want you comparing it with the value you’d get from an under-the-tongue thermometer or the thermometer used at your doctor’s office.
You can get the actual temperature readings from your watch by digging a little into the Health app. My temperature readings are generally a few degrees lower than my normal temperature measured by normal means.
By contrast, Apple will happily show you your blood oxygen reading:
I don’t believe this is any more trustworthy than the temperature. 95% is sort of a median value from my Health data, and it’s not unusual to see values as low as 90%. If the finger sensor in my doctor’s office ever showed readings like this, it would raise eyebrows. I don’t think I’ve ever seen my blood oxygen level less than 98% from those sensors.
Why is Apple more concerned about approximate temperatures than approximate blood oxygen levels? Beats me.