使用指定随机种子排序文件时遇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
相关产品推荐
相关产品推荐

