11

Is there a way to make a btrfs subvolume tree like what is shown below? (Only subvolumes - no regular directories or files.)

# tree /mnt/1
/mnt/1
├── a
├── snapshot
│   ├── a
│   └── subv
└── subv
    └── b

This example is created from a "sample" btrfs with no regular directories or files.
tree <mountpoint> shows all directories and files, not just the subvolumes. Using the -d option shows only directories, which is better, but still shows non-subvolume directories.

So, on an installed system, you get:

# tree /
/
├── bin -> usr/bin
├── boot
│   ├── grub
│   │   ├── fonts
│   │   │   └── unicode.pf2
│   │   ├── grub.cfg
│   │   ├── grub.cfg.example
│   │   ├── grubenv
│   │   ├── i386-pc
│   │   │   ├── 915resolution.mod
│   │   │   ├── acpi.mod
│   │   │   ├── adler32.mod
│   │   │   ├── affs.mod
... <over 242,000 lines snipped>
Paradox
  • 1,369
  • 3
  • 13
  • 27
user1902689
  • 1,178
  • 3
  • 12
  • 23
  • How about `tree -x`? It's not exactly what you asked for, but it may suit your purpose. – Celada Jun 25 '15 at 05:15
  • 2
    `btrfs subvolume list /` currently gives me 10 lines. `tree -x /` gives me over 108,000 lines. – user1902689 Jun 25 '15 at 05:27
  • Yeah, so then that's no good :-( I guess the trouble with your requirement is the question of what such a command should show if subvolumes `/a` and `/a/b/c` exist but the intermediate `/a/b` is not a subvolume but a regular directory. Omit the second level in the tree? But then where would `/a/z` appear if `/a/z` were a subvolume? Or show a blank placeholder in place of `/a/b` which isn't a subvolume? Also seems problematic. Anyway, maybe I'm just not imaginative enough to see the solution. Good luck. – Celada Jun 25 '15 at 05:34
  • @Celada - When I run `btrfs subvolume list /`, I see ID ### gen ### top level ### path . Is the top level number corresponding to the ID numbers? If so, I'd be happy for a tree generated on that basis, where top level 5 (at least on my system, indicating the "top-level" subvolumes) are shown, with recursive branches showing any subvolumes with that node's top level. I'm guessing it would probably have to be a btrfs-progs feature. – user1902689 Jun 25 '15 at 06:16
  • I'm working on putting together [a script for this](https://github.com/etskinner/svtree). So far I've populated objects of each subvolume in a btrfs file system with their children. Anyone who's interested in helping please feel free to submit a pull request. – etskinner May 10 '17 at 21:43
  • @etskinner - are you still working on svtree.py? I tried it and did not get expected output. – MountainX Jan 24 '20 at 02:48
  • @MountainX-for-Monica Apologies, I abandoned it before getting it to a fully working state – etskinner Jan 24 '20 at 02:52

1 Answers1

5

See this solution. It gets the list of subvols from btrfs command, strips the paths' column only, then passes through 2 tools: 1st converts path list to hierarchically indented text, 2nd adds ascii art tree in the place of indentation.

btrfs subvol list / | cut -f9 -d' ' | sed -e 's/^/ROOT\//' | paths2indent | indent2tree

You find these 2 perl scripts here: paths2indent and indent2tree

Example subvol list:

ID 1883 top level 5 path slash
ID 2004 top level 5 path logs
ID 2005 top level 5 path dbase
ID 2006 top level 5 path sdata
ID 2007 top level 5 path users
ID 2937 top level 5 path slash/snaps/by-procedure/quota-yazzy/users
ID 2938 top level 5 path slash/snaps/by-date/2019-11-21_0100/dbase
ID 2939 top level 5 path slash/snaps/by-date/2019-11-21_0100/slash
ID 2940 top level 5 path slash/snaps/by-date/2019-11-21_0100/logs
ID 2941 top level 5 path slash/snaps/by-date/2019-11-21_0100/sdata
ID 3004 top level 5 path slash/snaps/home/2019-12-04_0600

Example output:

ROOT
├── dbase
├── slash
│   └── snaps
│       ├── by-procedure
│       │   └── quota
│       │       └── users
│       ├── by-date
│       │   └── 2019-11-21_0100
│       │       ├── dbase
│       │       ├── slash
│       │       ├── sdata
│       │       └── logs
│       └── home
│           └── 2019-12-04_0600
├── users
├── sdata
└── logs

EDIT: newer versions output format differ, so change cut's field number if needed (-f7 vs. -f9).

bandie
  • 363
  • 4
  • 10