You marked your question with bash , so I will answer it as if you were asking how to do it in bash, instead of asking which language to use (which would make the question off-topic for StackOverflow).
You can analyze existing data from system_profiler using the built-in tools. For example, here is a supplier dump: product pairs, with a "Location ID" and a manufacturer ...
#!/bin/bash shopt -s extglob while IFS=: read key value; do key="${key##+( )}" value="${value##+( )}" case "$key" in "Product ID") p="${value% *}" ;; "Vendor ID") v="${value%% *}" ;; "Manufacturer") m="${value}" ;; "Location ID") l="${value}" printf "%s:%s %s (%s)\n" "$v" "$p" "$l" "$m" ;; esac done < <( system_profiler SPUSBDataType )
It depends on the fact that the Location ID is the last item specified for each USB device that I have not verified conclusively. (It seems to me that this is so.)
If you need something more readable (1) and (2) independent of bash and therefore more portable (not a problem, but all Mac computers come with bash), you may need to consider making your heavy lift in awk instead of pure bash:
#!/bin/sh system_profiler SPUSBDataType \ | awk ' /Product ID:/{p=$3} /Vendor ID:/{v=$3} /Manufacturer:/{sub(/.*: /,""); m=$0} /Location ID:/{sub(/.*: /,""); printf("%s:%s %s (%s)\n", v, p, $0, m);} '
Or do not even wrap the shell completely with the shell:
#!/usr/bin/awk -f BEGIN { while ("system_profiler SPUSBDataType" | getline) { if (/Product ID:/) {p=$3} if (/Vendor ID:/) {v=$3} if (/Manufacturer:/) {sub(/.*: /,""); m=$0} if (/Location ID:/) {sub(/.*: /,""); printf("%s:%s %s (%s)\n", v, p, $0, m)} } }
Note that you can also get the output from system_profiler in XML format:
$ system_profiler -xml SPUSBDataType
To process this output, you will need an XML parser. And you will find that this is a lot of work parsing XML in native bash.