随机化arg命令以获取bash for语句

时间:2009-12-16 19:26:39

标签: bash

我有一个bash脚本,它使用像

这样的循环处理目录中的所有文件

表示我在* .txt中 做    OPS ..... 完成

有数千个文件,由于'* .txt'扩展,它们总是以字母数字顺序处理。

是否有一种简单的方法来随机排序并仍然确保我只处理所有文件一次?

6 个答案:

答案 0 :(得分:3)

您可以通过sort命令管道文件名:

ls | sort --random-sort | xargs ....

答案 1 :(得分:3)

假设文件名没有空格,只需替换List::Util::shuffle的输出。

for i in `perl -MList::Util=shuffle -e'$,=$";print shuffle<*.txt>'`; do
    ....
done

如果文件名确实有空格但没有嵌入换行符或反斜杠,请一次读一行。

perl -MList::Util=shuffle -le'$,=$\;print shuffle<*.txt>' | while read i; do
    ....
done

要在Bash中完全安全,请使用以NUL结尾的字符串。

perl -MList::Util=shuffle -0 -le'$,=$\;print shuffle<*.txt>' |
while read -r -d '' i; do
    ....
done

效率不高,但如果需要,可以在纯Bash中执行此操作。 sort -R在内部做了类似的事情。

declare -a a                     # create an integer-indexed associative array
for i in *.txt; do
    j=$RANDOM                    # find an unused slot
    while [[ -n ${a[$j]} ]]; do
        j=$RANDOM
    done
    a[$j]=$i                     # fill that slot
done
for i in "${a[@]}"; do           # iterate in index order (which is random)
    ....
done

或使用传统的Fisher-Yates shuffle。

a=(*.txt)
for ((i=${#a[*]}; i>1; i--)); do
    j=$[RANDOM%i]
    tmp=${a[$j]}
    a[$j]=${a[$[i-1]]}
    a[$[i-1]]=$tmp
done
for i in "${a[@]}"; do
    ....
done

答案 2 :(得分:1)

这是一个答案,它依赖于awk中的非常基本的功能,所以它应该在unices之间移植。

ls -1 | awk '{print rand()*100, $0}' | sort -n | awk '{print $2}'

编辑:

eppeient提出了一个很好的观点,即上述不是空间安全的。这是一个版本:

ls -1 | awk '{print rand()*100, $0}' | sort -n | sed 's/[0-9\.]* //'

答案 3 :(得分:1)

以下是使用标准unix命令的解决方案:

for i in $(ls); do echo $RANDOM-$i; done | sort | cut -d- -f 2-

答案 4 :(得分:1)

如果你有GNU coreutils,你可以使用shuf

while read -d '' f
do
    # some stuff with $f
done < <(shuf -ze *)

这适用于名称中带有空格或换行符的文件。

偏离主题的修改:

在评论中说明 SiegeX的点:

$ a=42; echo "Don't Panic" | while read line; do echo $line; echo $a; a=0; echo $a; done; echo $a
Don't Panic
42
0
42
$ a=42; while read line; do echo $line; echo $a; a=0; echo $a; done < <(echo "Don't Panic"); echo $a
Don't Panic
42
0
0

管道导致while在子shell中执行,因此子项中变量的更改不会回流到父项。

答案 5 :(得分:0)

这是一个Python解决方案,如果它在您的系统上可用

import glob
import random
files = glob.glob("*.txt")
if files:
    for file in random.shuffle(files):
        print file