You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用指定随机种子排序文件时遇sort: /dev/fd/63错误求助

解决sort: /dev/fd/63: end of file错误(指定种子的目录文件随机排序问题)

你遇到的这个错误是因为GNU bash 4.2的进程替换特性和sort的--random-source参数配合时存在兼容性问题——老版本bash在处理<(...)生成的文件描述符时,可能会在子进程(这里是openssl)还没输出足够数据就提前关闭管道,导致sort读取到文件末尾的错误。

下面给你几个可靠的解决方案,按推荐程度排序:

方案1:用awk实现跨版本兼容的带种子随机排序

这个方法完全避开sort的--random-source限制,兼容性最好,适合bash 4.2这类老版本:

#!/bin/bash
# 检查是否传入种子参数
if [ -z "$1" ]; then
    echo "请传入随机种子参数,比如: $0 405"
    exit 1
fi

seed="$1"
# 用awk生成带随机数的行,排序后去掉随机数部分
ls | awk -v seed="$seed" 'BEGIN{srand(seed)} {print rand(), $0}' | sort -n | cut -d' ' -f2-

原理

awk的srand(seed)可以设置随机数生成器的种子,确保每次用相同种子得到完全一致的排序结果。我们给每个文件名前加一个对应的随机数,按随机数排序后再去掉这个数,就实现了稳定的带种子随机排序。

方案2:改用临时文件存储随机数据

如果坚持想用sort的--random-source,我们可以把openssl生成的随机数据写入临时文件,避免进程替换的管道问题:

#!/bin/bash
if [ -z "$1" ]; then
    echo "请传入随机种子参数,比如: $0 405"
    exit 1
fi

# 创建临时文件,脚本退出时自动删除
temp_random=$(mktemp)
trap 'rm -f "$temp_random"' EXIT

# 生成足够的随机数据写入临时文件
get_seeded_random() {
    seed="$1"
    # 输出4MB随机数据,足够sort使用
    openssl enc -aes-256-ctr -pass pass:"$seed" -nosalt </dev/zero 2>/dev/null | dd bs=1M count=4 2>/dev/null > "$temp_random"
}

get_seeded_random "$1"
ls | sort -R --random-source="$temp_random"

原理

临时文件不会像进程替换的管道那样提前关闭,sort可以稳定读取到足够的随机数据,dd命令确保我们生成足够多的随机字节(4MB完全满足sort的需求)。

方案3:修复原脚本的进程替换问题

如果你不想改逻辑,也可以给openssl的输出加一个循环,确保持续输出数据直到sort读取完成:

#!/bin/bash
if [ -z "$1" ]; then
    echo "请传入随机种子参数,比如: $0 405"
    exit 1
fi

get_seeded_random() {
    seed="$1"
    # 持续输出随机数据,直到管道关闭
    while true; do
        openssl enc -aes-256-ctr -pass pass:"$seed" -nosalt </dev/zero 2>/dev/null
    done
}

ls | sort -R --random-source=<(get_seeded_random "$1")

原理

while true循环让openssl持续输出随机数据,直到sort完成读取并关闭管道,这样就不会出现"end of file"的错误。

你可以根据自己的需求选择方案,个人推荐方案1,因为它不需要依赖openssl和sort的特定参数,在各种bash版本下都能稳定运行。

内容的提问来源于stack exchange,提问作者Min Chen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:40:39