更改lsblk排序顺序

更改lsblk排序顺序

更改lsblk排序顺序

lsblk按难以遵循的顺序对分区进行排序。无需编写 bash 脚本或 python 脚本即可对其进行排序的方法将是首选。

在Unix&Linux中也提出了类似的问题:

然而,使用参数进行排序的答案-x NAME导致树缩进消失。

当前排序顺序

现在的显示方式如下lsblk

$ 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 

建议排序顺序

lsblk排序方式如下:

$ 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 

笔记: lsdrv是在中定义的别名~/.bashrc

$ alias lsdrv

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

概括

更改排序顺序的复杂性包括:

  • 只有带有线绘制字符的分区├─└─按其驱动器排序。
  • 对分区进行排序后,最后一个分区可能需要├─替换为└─
  • 对分区进行排序后,第一个分区到倒数第二个分区可能需要└─替换为├─
  • 老人“阿喀琉斯之踵”10对之后的位置进行排序11例如然后10然后2。确实9应该出现在之前10

的排序方式lsblk多年来一直是个难题。希望有人能用 GNU 实用程序找到一个简单的解决方案,例如:、、awk和/或等。sedgrepuniqsort

答案1

我最终编写了一个通用排序函数来解决这个问题。

新的lsblk排序顺序

$ 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 

lsblk用于对输出进行排序的 Bash 脚本

我花了几个小时在 Google 上搜索不同的 bash 命令才找到解决方案。这个 bash 脚本最初名为sblk,可以用于其他用途:

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

相关内容