1

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,

/usr/bin/sysdiagnose

  • #!/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:

#!/bin/sh
for dataset in `zfs list -H | cut -f 1`
do
  zfs get all $dataset
done

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":

#!/bin/sh
data_directory_path=~/Desktop
ECHO=/bin/echo
ZFS=/usr/sbin/zfs
ZPOOL=/usr/sbin/zpool
# If there exists a zfs binary, get some ZFS information
if [ -f "${ZFS}" ]
then
    "${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"
    OLD_IFS=$IFS
    IFS=$'\n'
    for dataset in `zfs list -H | cut -f 1`
    do
        "${ZFS}" get all "$dataset" &> ${data_directory_path}/ZFS\ file\ system\ properties.txt
    done
    IFS=$OLD_IFS
    "${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
fi

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.

3
  • Chat, with reference to the second edition of this question: chat.stackexchange.com/transcript/message/7661588#7661588 Jan 14, 2013 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. Jan 16, 2013 at 7:23
  • Appreciating the age of the question and that it might have been simplified for brevity, what was wrong with simply for DS in $(zfs list -H -o name); do zfs get all "$DS"; done? I've been using that idiom in my own scripts for a while and am hoping I haven't missed anything (note the use of -o name and "-quoting to limit the output (no longer needs cut) and handle spaces in dataset names (even though space is supposed to be an invalid char for dataset names) Jul 15, 2019 at 11:52

1 Answer 1

2
+50

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.

#!/bin/bash
IFS=$'\n'
for dataset in `zfs list -H | cut -f 1`
do
  zfs get all "$dataset"
done

Resetting IFS

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

OLD_IFS=$IFS
# the whitespaces-sensitive lines
IFS=$OLD_IFS
4
  • 1
    This (paste) results in properties for only one dataset. An alternative approach fails in a different way. pastebin.com/nJQZq64s shows datasets at the time of writing. Should I edit the original question to include more detail? Jan 15, 2013 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, 2013 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 … Jan 16, 2013 at 0:42
  • 1
    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, 2013 at 2:11

You must log in to answer this question.

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