更改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
对之后的位置进行排序1
,1
例如然后10
然后2
。确实9
应该出现在之前10
。
的排序方式lsblk
多年来一直是个难题。希望有人能用 GNU 实用程序找到一个简单的解决方案,例如:、、awk
和/或等。sed
grep
uniq
sort
答案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