Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'd like to take output from two commands –

zpool list
zfs list

and for each found pool:

zpool get all nameofpool

and for each found file system:

zfs get all nameoffilesystem

Background and environment

I'm making local changes to script that's integral to OS X,


  • #!/bin/sh for starters
  • always run with superuser privileges
  • sometimes effectively headless (triggered by a key chord), so the output must be a file.

First experiment

Based on the example at #65 Remove all ZFS snapshots:

for dataset in `zfs list -H | cut -f 1`
  zfs get all $dataset

That works, but not where there's a space in the name of the dataset. For example where the file system is zhandy/Pocket Time Machine the output includes:

cannot open 'zhandy/Pocket': dataset does not exist
cannot open 'Time': dataset does not exist
cannot open 'Machine': dataset does not exist

 Second experiment

… was based on the first answer to this question – using IFS – and made the script more like Apple's. See revision 4.

Third experiment

Based on the accepted answer to this question – with IFS, and quotation marks for "$dataset":

# If there exists a zfs binary, get some ZFS information
if [ -f "${ZFS}" ]
    "${ECHO}" "Recording ZFS pool version information ..."
    "${ZPOOL}" upgrade &> ${data_directory_path}/zpool\ upgrade.txt
    "${ECHO}" "    listing all ZFS pools ..."
    "${ZPOOL}" list &> ${data_directory_path}/zpool\ list.txt
    "${ECHO}" "    detailed health status and verbose data error information ..."
    "${ZPOOL}" status -v &> ${data_directory_path}/zpool\ status.txt
    "${ECHO}" "    pools that are available but not currently imported"
    "${ZPOOL}" import &> ${data_directory_path}/zpool\ import.txt
    "${ECHO}" "Recording ZFS file system version information ..."
    "${ZFS}" upgrade &> ${data_directory_path}/zfs\ upgrade.txt
    "${ECHO}" "    listing all ZFS file systems ..."
    "${ZFS}" list &> ${data_directory_path}/zfs\ list.txt
    "${ECHO}" "    all properties of each file system"
    for dataset in `zfs list -H | cut -f 1`
        "${ZFS}" get all "$dataset" &> ${data_directory_path}/ZFS\ file\ system\ properties.txt
    "${ECHO}" "Listing the contents of /dev/dsk"
    "${LS}" -@adel /Volumes &> ${data_directory_path}/ls-dev-dsk.txt
    "${ECHO}" "Listing the contents of /var/zfs/dsk"
    "${LS}" -@adel /Volumes &> ${data_directory_path}/ls-var-zfs-dsk.txt

Amongst the resulting files, ZFS file system properties.txt lists properties for just one ZFS file system … a dataset with white space in its name.

The most desirable end result is properties:

  • for all ZFS file systems
  • in a file.

Removing the following string –

&> ${data_directory_path}/ZFS\ file\ system\ properties.txt

– does get properties for all ZFS file systems, in a window of Terminal but not in a file. That's enough for me to accept an answer.

The output to file criterion, which wasn't in my first edition of the question, may be easily answered elsewhere.

share|improve this question
Chat, with reference to the second edition of this question: – Graham Perrin Jan 14 '13 at 9:30
Alongside the accepted answer below, with this answer (to How can I take the output of a shell script and place it in a file on the command line?) I realise that for the output to file – for the append – I need >> (not &> or &>>). In feedback to Apple I asked for sysdiagnose to be added to Apple Open Source – if this happens I'll make public my other changes to the script, most of which are unrelated to ZFS. – Graham Perrin Jan 16 '13 at 7:23
up vote 2 down vote accepted

Not splitting at spaces

bash's for loop splits the argument at all whitespace characters by default. You could somehow escape each line - or simply switch to another delimiter character. cut will return one value per line, so there's a newline in between which we can choose.

Watch out for the double quotes in zfs get all, so each $dataset doesn't get split up, too.

for dataset in `zfs list -H | cut -f 1`
  zfs get all "$dataset"

Resetting IFS

Afterwards, you might want to reset IFS to the value before, store it to some temporary variable.

# the whitespaces-sensitive lines
share|improve this answer
This (paste) results in properties for only one dataset. An alternative approach fails in a different way. shows datasets at the time of writing. Should I edit the original question to include more detail? – Graham Perrin Jan 15 '13 at 20:52
Aye, using /bin/sh does work for me on OS X (links to bash here), but I'm experiencing same problems on ubuntu linux (linking sh to dash). Try changing the shebang (see updated answer), dash doesn't seem to interprete the \n as newline but 'n' character instead. PS: +1 for own effort in solving problem and adding a link to the zfs list output to the question wouldn't hurt anyone but offer some reference. By the way, looks your tabs got replaced by spaces while uploading, had to undo that before cut working properly. – Jens Erat Jan 15 '13 at 23:05
/bin/bash did not workaround. I edited the question to include more context, and to show more clearly how I'm experimenting based on this answer. Partial success. I could be making some very basic mistake somewhere! Thanks … – Graham Perrin Jan 16 '13 at 0:42
Oh, you have another problem, that's not the one I had - didn't realize this while digging to your pastes for the first time... Using printf was unnecessarily complicated anyway, just wrap it in double quotes: zfs get all "$dataset". I guess it should run fine now. – Jens Erat Jan 16 '13 at 2:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .