Score:3

How to change `lsblk` sort order?

in flag

Change lsblk sort order

lsblk sorts partitions in an order that is hard to follow. A method of sorting it without having to write a bash script or python script would be the first choice.

A similar question was asked in Unix & Linux:

However the answer there to use -x NAME parameter for sorting causes the tree indenting to disappear.

Current sort order

This is how lsblk displays now:

$ lsdrv

NAME         FSTYPE   LABEL            MOUNTPOINT                    SIZE MODEL
nvme0n1                                                              477G Samsung SSD 960 PRO 512GB               
├─nvme0n1p9  swap                      [SWAP]                        7.9G 
├─nvme0n1p7  ext4     Old_Ubuntu_16.04 /mnt/old                     23.1G 
├─nvme0n1p5  ntfs                                                    859M 
├─nvme0n1p3                                                           16M 
├─nvme0n1p1  ntfs                                                    450M 
├─nvme0n1p8  ntfs     Shared_WSL+Linux /mnt/e                          9G 
├─nvme0n1p10 ext4     Ubuntu_18.04     /mnt/clone                   27.2G 
├─nvme0n1p6  ext4     New_Ubuntu_16.04 /                            45.1G 
├─nvme0n1p4  ntfs     NVMe_Win10       /mnt/c                      363.2G 
└─nvme0n1p2  vfat                      /boot/efi                      99M 
mmcblk0                                                            119.1G 
└─mmcblk0p1  vfat     SANDISK128       /media/rick/SANDISK128      119.1G 
sr0                                                                 1024M DVD+/-RW DW316  
sda                                                                931.5G HGST HTS721010A9
├─sda4       ntfs     WINRETOOLS                                     450M 
├─sda2                                                               128M 
├─sda5       ntfs     Image                                         11.4G 
├─sda3       ntfs     HGST_Win10       /mnt/d                        919G 
└─sda1       vfat     ESP                                            500M 

Proposed sort order

This is how it lsblk should be sorted:

$ lsdrv

NAME         FSTYPE   LABEL            MOUNTPOINT                    SIZE MODEL
nvme0n1                                                              477G Samsung SSD 960 PRO 512GB               
├─nvme0n1p1  ntfs                                                    450M 
├─nvme0n1p2  vfat                      /boot/efi                      99M 
├─nvme0n1p3                                                           16M 
├─nvme0n1p4  ntfs     NVMe_Win10       /mnt/c                      363.2G 
├─nvme0n1p5  ntfs                                                    859M 
├─nvme0n1p6  ext4     New_Ubuntu_16.04 /                            45.1G 
├─nvme0n1p7  ext4     Old_Ubuntu_16.04 /mnt/old                     23.1G 
├─nvme0n1p8  ntfs     Shared_WSL+Linux /mnt/e                          9G 
├─nvme0n1p9  swap                      [SWAP]                        7.9G 
└─nvme0n1p10 ext4     Ubuntu_18.04     /mnt/clone                   27.2G 
mmcblk0                                                            119.1G 
└─mmcblk0p1  vfat     SANDISK128       /media/rick/SANDISK128      119.1G 
sr0                                                                 1024M DVD+/-RW DW316  
sda                                                                931.5G HGST HTS721010A9
├─sda1       vfat     ESP                                            500M 
├─sda2                                                               128M 
├─sda3       ntfs     HGST_Win10       /mnt/d                        919G 
├─sda4       ntfs     WINRETOOLS                                     450M 
└─sda5       ntfs     Image                                         11.4G 

Note: lsdrv is an alias defined in ~/.bashrc:

$ alias lsdrv

alias lsdrv='lsblk -o NAME,FSTYPE,LABEL,MOUNTPOINT,SIZE,MODEL |egrep -v "^loop"'

Summary

Complexities of changing sort order are:

  • Only partitions with line draw characters ├─ and └─ are sorted under their drives.
  • After sorting partitions, the last partition may need ├─ replaced with └─.
  • After sorting partitions, the first partition to second last partition may need └─ replaced with ├─.
  • The old "Achilles' heel" of sorting places 10 after 1 , E.G. 1 then 10 then 2 . Really 9 should appear before 10.

The sort order of lsblk has been a thorn for years. Hopefully someone has a simple solution with GNU utiliies like: awk, sed, grep, uniq and/or sort, etc.

waltinator avatar
it flag
Read `man stat`, you can write your own `lsblk`-like with your own output format
Terrance avatar
id flag
`lsblk --tree -x NAME | grep -v loop` should work fine, but I am not sure how to list like nvme0n1p2 before nvme0n1p10 since the sort order is by the first then second digits. Hmmmmmm
WinEunuuchs2Unix avatar
in flag
@Terrance The version `lsblk from util-linux 2.27.1` gives an error message with `--tree` parameter: `lsblk: unrecognized option '--tree'`. What version of `lsblk` are you using? E.G. `lsblk --version`.
WinEunuuchs2Unix avatar
in flag
@waltinator Rather than writing a new command from scratch with the `stat` command, it might be easier taking the `lsblk` source code and modifying it.
heynnema avatar
ru flag
I suspect that lsblk shows partitions in actual physical order as found on disk. If that's accurate, then you really don't want to sort them just to look pretty. Also, it looks like you may have a partitioning nightmare anyway. Sorry. What does gparted show?
WinEunuuchs2Unix avatar
in flag
@heynnema But I like pretty :) `gparted` does show a nightmare and this Question was asked during a project to start merging partitions together for Ubuntu 22.04 LTS install. As far as how `lsblk` is displaying them now you might be correct but that doesn't concern me at this time...
heynnema avatar
ru flag
You running 22.04? And give up 16.04 and 18.04? That's blasphemy! Giggle. Don't merge partitions... wipe it and start fresh... get rid of the nightmare.
waltinator avatar
it flag
Dealing with "pretty-printing" with text processing tools is hard, and is hardly ever worth the effort. Ignoring the actual partition order and the nightmare has high risk of data loss.
oldfred avatar
cn flag
I am using 20.04 and lsblk lists partitions in numerical order. They are not in that order on the drives.
heynnema avatar
ru flag
I can confirm... on 21.10... lsblk lists in numerical order.
WinEunuuchs2Unix avatar
in flag
@waltinator I agree it is not a simple task. But when something bugs you for years, you just can't resist the urge to fix it. I just posted a solution.
WinEunuuchs2Unix avatar
in flag
@heynnema I used to wipe out and reinstall. Last five years I've come to dread the process :( I'm more content spending my free-time developing software. BTW I did post an answer just now.
WinEunuuchs2Unix avatar
in flag
@oldfred When you type `lsblk --version` what does it say? And does output look similar to my answer I just posted below?
Terrance avatar
id flag
@WinEunuuchs2Unix `lsblk from util-linux 2.34`
heynnema avatar
ru flag
@WinEunuuchs2Unix from 21.10... `lsblk from util-linux 2.36.1`
heynnema avatar
ru flag
@WinEunuuchs2Unix re: *"I used to wipe out and reinstall. Last five years I've come to dread the process"*... what's been the problem?
WinEunuuchs2Unix avatar
in flag
@heynnema The problem is I've forgotten the many programs I need to reinstall and how to configure them to perform in a manner I prefer. My next project will be to fresh install 22.04 and automatically reinstall all the programs on an old partition plus bring in data from old partition. Also bring in `/etc` and `~/.config/` configuration files from old partition. Quite simply I need this because A) I forgot what I installed, or B) I'm too lazy to do it one by one myself, or C) Skipping multiple LTS versions or Minor versions at one time.
heynnema avatar
ru flag
@WinEunuuchs2Unix You might be able to use `Synaptic's` **Generate Package Download Script** (File menu) to automate some of that.
WinEunuuchs2Unix avatar
in flag
@heynnema Thanks for the tip. I would prefer not to totally "reinvent the wheel" because the first few versions tend to be square and don't roll at all.
heynnema avatar
ru flag
@WinEunuuchs2Unix I don't quite understand what you mean.
oldfred avatar
cn flag
Only because asked, since otherwise resolved. fred@z170-focal-k:~$ lsblk --version `lsblk from util-linux 2.34`
Score:3
in flag

I ended up writing a generic sorting function to solve the problem.

New lsblk sort order

$ lsdrv | sblk

NAME         FSTYPE   LABEL            MOUNTPOINT                    SIZE MODEL
nvme0n1                                                              477G Samsung SSD 960 PRO 512GB               
├─nvme0n1p1  ntfs                                                    450M 
├─nvme0n1p2  vfat                      /boot/efi                      99M 
├─nvme0n1p3                                                           16M 
├─nvme0n1p4  ntfs     NVMe_Win10       /mnt/c                      363.2G 
├─nvme0n1p5  ntfs                                                    859M 
├─nvme0n1p6  ext4     New_Ubuntu_16.04 /                            45.1G 
├─nvme0n1p7  ext4     Old_Ubuntu_16.04 /mnt/old                     23.1G 
├─nvme0n1p8  ntfs     Shared_WSL+Linux /mnt/e                          9G 
├─nvme0n1p9  swap                      [SWAP]                        7.9G 
└─nvme0n1p10 ext4     Ubuntu_18.04     /mnt/clone                   27.2G 
mmcblk0                                                            119.1G 
└─mmcblk0p1  vfat     SANDISK128       /media/rick/SANDISK128      119.1G 
sr0                                                                 1024M DVD+/-RW DW316  
sda                                                                931.5G HGST HTS721010A9
├─sda1       vfat     ESP                                            500M 
├─sda2                                                               128M 
├─sda3       ntfs     HGST_Win10       /mnt/d                        919G 
├─sda4       ntfs     WINRETOOLS                                     450M 
└─sda5       ntfs     Image                                         11.4G 

Bash script to sort lsblk output

It took a couple hours of googling different bash commands to make a solution. The bash script, initially called sblk, can be adapted for other purposes:

#!/bin/bash
# Ask Ubuntu: https://askubuntu.com/questions/1392560/how-to-change-lsblk-sort-order
oIFS="$IFS"                         # Save IFS
IFS='|'                             # Use "|" as array delimiter
declare -a partiions=()             # Partitions array for a given drive

add_part () {
    line="$1"                       # Confusing parameter $1 becomes obvious
    part=${line%% *}                # get partition name, then get number
    key=$(echo "$part" | grep -Eo '[0-9]+$')

    # If length of number is less than 2, prepend "0"
    if [[ "${#key}" < 2 ]]; then
        key="0$key"                 # Prepend "0" to single digit
    fi

    line="${line:2}"                # Strip out tree character
    partitions+=( "$key$line" )     # Old line "├─..." now array entry "99..."
}

sort_parts () {
    # Sort partitions array with sort key into new "sorted" array
    read -r -d '' -a sorted < <( 
        echo "${partitions[*]}" | tr "|" "\n" | sort | tr "\n" "|" )
    last_i=$(( ${#sorted[@]} - 1 )) # Last 0-based index in sorted array

    for ((i=0; i <= $last_i; i++)); do
        line="${sorted[i]}"         # Get array line at 0-based index
        line="${line:2}"            # Strip out sort key "99"
        if [[ $i -lt $last_i ]]; then
            echo "├─$line"          # Print a line that is not the last line
        else
            echo "└─$line"          # Print last line
        fi
    done
    partitions=()                   # Empty partitions array for the next drive
}

# Main Loop
while read line
do
    first="${line:0:2}"
    if [[ "$first" == "├─" || "$first" == "└─" ]]; then
        add_part "$line"            # Add special line to partitions array

        if [[ "$first" == "└─" ]]; then
            sort_parts              # Last partition. Sort and print array
        fi
    else
        echo "$line"                # Simply print a regular line
    fi

done < "${1:-/dev/stdin}"           # Read from file $1 or from standard input


IFS="$oIFS"                         # Restore old IFS
Terrance avatar
id flag
Very good! No need to worry about the `lsblk` version. +1 my friend! :)
heynnema avatar
ru flag
+1 for persistence :-)
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.