1

When I boot into single-user mode and list the ZFS snapshots I'm interested in, I want to revert to the "xfcedesktop" snapshot. However, this requires me to manually type the command zfs rollback snapshotname@xfcedesktop for each snapshot, like this:

# zfs list -t snapshot -o name | grep xfcedesktop
zroot@xfcedesktop
zroot/ROOT@xfcedesktop
zroot/ROOT/default@xfcedesktop
zroot/home@xfcedesktop
zroot/home/zoliky@xfcedesktop
zroot/tmp@xfcedesktop
zroot/usr@xfcedesktop
zroot/usr/ports@xfcedesktop
zroot/usr/src@xfcedesktop
zroot/var@xfcedesktop
zroot/var/audit@xfcedesktop
zroot/var/crash@xfcedesktop
zroot/var/log@xfcedesktop
zroot/var/mail@xfcedesktop
zroot/var/tmp@xfcedesktop

# now I need to type this for each line:
zfs rollback zroot@xfcedesktop
zfs rollback zroot/ROOT@xfcedesktop
zfs rollback zroot/ROOT/default@xfcedesktop
.. and so on

This is time consuming and prone to mistakes. I'm wondering if there's a shell trick or a one-liner that would let me loop through the output of grep and execute the rollback commands for each snapshot. I'm using sh (not bash) on FreeBSD, running in single-user mode. Ideally, I'd like it to be a one-liner rather than a script.

3 Answers 3

2

Use either a simple while loop, as in

zfs list -H -t snapshot -o name | grep '@xfcedesktop$' |
while IFS= read -r snapshot; do
    zfs rollback "$snapshot"
done

... or use xargs

zfs list -H -t snapshot -o name | grep '@xfcedesktop$' |
xargs -r -I {} zfs rollback {}

The -r option to xargs is supported but unnecessary on FreeBSD. With GNU's xargs, the option prevents the utility from trying to run the utility if the input is empty. This is the default behaviour of FreeBSD's xargs.

I've also been more careful with the regular expression used with grep to ensure we only get the expected snapshots (the ones ending in exactly @xfcedesktop).

2
  • Thank you. Can the while loop be written on a single line? Commented Feb 25 at 13:21
  • @ZoltanKing while IFS= read -r snapshot; do zfs rollback "$snapshot"; done Commented Feb 25 at 13:22
1

This isn't copy-n-paste - remove ## to end of line. I'm using ## comments to explain.

zfs list -t snapshot | grep xfcedesktop | \
  untabify | \ ## change TABs to SPACEs.
  cut "-d " -f1 | \ ## first space delimited field
  xargs -n 1 -r | \ ## apply 1 at a time to
    echo zfs rollback

Remove the echo command when you're happy with the output.

4
  • 1
    I have never heard of untabify but get the idea. It is not part of FreeBSD base. Linuxism? Maybe available in pkg/ports? For FreeBSD I would suggest using unexpand(1) as unexpand -a instead as it is part of the base OS. Otherwise I love this answer which is concise, explanatory and safeguards with an echo! Commented Feb 25 at 9:26
  • I updated my post. I can get only the first column with zfs list -t snapshot -o name so there's no need to deal with spaces or tabs. Commented Feb 25 at 11:41
  • I was thinking if there's anything wrong with this approach: zfs list -t snapshot -o name | grep "xfce" | while IFS= read -r snapshot; do zfs rollback "$snapshot"; done ? Commented Feb 25 at 11:42
  • Add -Ho name to the zfs list and do away with all the untabify and cut stuff. But even then, this will fail on names containing spaces. Commented Feb 25 at 23:46
1

Both solutions have positive aspects. And I generally use a very simple awk command when batching a number of ZFS filesystems or snapshots.

Combining the wise use of -Ho name along with the "look-before-you-leap" approach of echoing commands before you execute them, I suggest:

zfs list -Hrt snap -o name zroot |
    awk '/@xfcedesktop$/ {print "zfs rollback \"" $0 "\""}'

If you like the commands you see, up-arrow to that command and add | sh to execute the zfs rollback commands.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.