Find specific attached disk, not volume, by Applescript

applescriptdisk-formatdiskutil

I have a script I use to format any inserted SD card, copy data from specific folders to it, then eject.

Each format/copy is triggered manually, as part of a batch process involving maybe a hundred or so cards, so I'm not concerned about hitting the Start button at the wrong time, or on the wrong card.

What I am trying to find is how to make absolutely sure that I'm writing to the correct disk

This is my 'important' line
do shell script "diskutil eraseDisk \"MS-DOS FAT16\" " & diskName & " MBRFormat disk6"

The disk6 is not absolute, as I don't always have the same number of drives mounted. I can check it manually before I start the batch, using diskutil list then change that parameter in the script.

What I'd like to be able to do is have the script itself check what drive it ought to be, then insert that as a variable, avoiding any 'wrong choices'.

Excluded drives would be non-removables & RAM Disks [presumably unmounted volumes such as EFI & Recovery wouldn't need to be filtered] – these have known volume names – but I cannot figure out how to set a found volume name [known or unknown, as the SD cards can be called pretty much anything before I start] to a specific disk number.


Specifics on the card reader, built into my monitor, Dell U2713H
Attached over USB2 from a Mac Pro 4,1 [with 5,1 hardware update]

USB Hi-Speed Bus:

  Host Controller Location: Built-in USB
  Host Controller Driver:   AppleUSBEHCI
  PCI Device ID:    0x3a3c 
  PCI Revision ID:  0x0000 
  PCI Vendor ID:    0x8086 
  Bus Number:   0xfa 

Hub:

  Product ID:   0x8043
  Vendor ID:    0x0451  (Texas Instruments)
  Version:  1.00
  Serial Number:    79000089BFB9
  Speed:    Up to 480 Mb/sec
  Location ID:  0xfa200000 / 2

//snips other devices//

USB3.0 Card Reader:

  Product ID:   0x0307
  Vendor ID:    0x0bda  (Realtek Semiconductor Corp.)
  Version:  1.63
  Serial Number:    201006010301
  Speed:    Up to 480 Mb/sec
  Manufacturer: Realtek
  Location ID:  0xfa233000 / 5

Sample output of df

Filesystem    512-blocks       Used  Available Capacity   iused     ifree %iused  Mounted on
/dev/disk1s2  1950314272  485618064 1464184208    25%  60766256 183023026   25%   /
devfs                412        412          0   100%       714         0  100%   /dev
/dev/disk0s2  3906357344 1195025808 2711331536    31% 149378224 338916442   31%   /Volumes/JuSpace
/dev/disk3s2  1951855464  635192376 1316663088    33%  79399045 164582886   33%   /Volumes/Downloads
/dev/disk2s2  5858067520 2309215360 3548852160    40% 144325958 221803260   39%   /Volumes/OhDaSpace
/dev/disk4s2  5753889792 4638480736 1115409056    81% 289905044  69713066   81%   /Volumes/TMach
map -hosts             0          0          0   100%         0         0  100%   /net
map auto_home          0          0          0   100%         0         0  100%   /home
/dev/disk3s4   408324240  210669592  197654648    52%    200589  98828207    0%   /Volumes/MacWin7
/dev/disk5       2097152     700536    1396616    34%     87565    174577   33%   /Volumes/RAM Disk
/dev/disk7s1     1936768     104192    1832576     6%       512         0  100%   /Volumes/F_CARD

Or…
Using ioreg -l with the following result

| |   |   |             +-o Generic- SD/MMC/MS/MSPRO Media  <class IOMedia,$
| |   |   |               | {
| |   |   |               |   "Removable" = Yes
| |   |   |               |   "Content" = "FDisk_partition_scheme"
| |   |   |               |   "Whole" = Yes
| |   |   |               |   "Leaf" = No
| |   |   |               |   "BSD Name" = "disk7"

how do I fix something like grep -A 100 SD/MMC/MS/MSPRO Media | grep disk | awk... to find the disk7

Best Answer

I'm not that great in writing Apple scripts but here is an idea how to solve your problem.

In the first method outlined below I search the device tree of system_profiler to get the DiskIdentifier of a disk device attached to the USB3 card reader built into your Dell monitor. In the second method I use ioreg.

system_profiler:

To get the DiskIdentifier of a SD-card attached to the external SD-Reader use something like:

system_profiler -detailLevel mini | grep -A 30 0x0307 | awk '/disk/ {gsub("BSD Name:", ""); print $NF}'

with grep -A 30 0x0307: output the next 30 lines after finding the string 0x0307
and awk '/disk/ {gsub("BSD Name:", ""); print $NF}' to get the disk number but remove BSD Name: from the output.

The command takes about 10 seconds on my system.

You may have to adjust the value of -A and the characteristic string (in the example above I used your USB3.0 Card Reader Product ID: 0x0307). Check the device tree with the app System Information and search for an appropriate string.

Wrap all that in a variable like $SDDiskToErase and hand it over to your diskutil eraseDisk command.

Using the above slightly modified line I got the diskIdentifier (disk2) of an external USB disk directly attached to my Mac:

system_profiler -detailLevel mini | grep -A 30 0x1c26 | awk '/disk/ {gsub("BSD Name:", ""); print $NF}'
disk2

ioreg:

Another initial command is ioreg -l | grep … (… is similar to the above) which is much faster (less than a second).

Attach an SD-card and get its DiskIdentifier with diskutil list. Then make a dump of ioreg with ioreg -l > ~/Desktop/ioreg-dump.txt.

Search in ioreg-dump.txt for the diskIdentifier found above. The disk is connected to a superior controller (the one in your monitor) visualized by the long vertical and short horizontal "lines" on the left in the dumb file. Use a characteristic and unique string of the controller like a serial number, IOName, deviceID etc. Then choose a number of subsequent lines for -A big enough to contain the diskIdentifier (e.g. disk6) but small enough not to contain the volume identifiers (e.g. disk6s1).

Example:

ioreg -l | grep -A 350 0x100000214 | awk '/disk/ {gsub("\"",""); print $NF}'
disk2

To use the command in Apple Script you have to escape all inner " and \:

"ioreg -l | grep -A 10 SD/MMC/MS/MSPRO | awk '/disk/ {gsub("\"",""); print $NF}'"

becomes:

do shell script "ioreg -l | grep -A 10 SD/MMC/MS/MSPRO | awk '/disk/ {gsub(\"\\\"\",\"\"); print $NF}'"