How can I shuffle an array of filenames that have spaces in them?

痞子三分冷 提交于 2019-12-11 03:08:10

问题


I have an array of filenames that may contain spaces in them. I am using the shuf command but it uses the spaces in the filenames as a delimiter and breaks up the filenames when it shuffles. Is there a way around this or do I have to abandon the shuf command? Any suggestions?

#!/bin/bash

vids=()

vids+=("file with spaces.txt")

for arr in "${vids[@]}"; do
    echo -e "$arr\n"
done

vids=( $(shuf -e "${vids[@]}") )    #shuffle contents of array

for arr in "${vids[@]}"; do
    echo -e "$arr\n"
done

exit 0

Ouput:

file with spaces.txt

file

with

spaces.txt

回答1:


The reason your approach doesn't work is that the shell applies word splitting to the output of a command inside $(...), and there's no way to treat newlines as a separator. You could either use mapfile to read lines into an array (in Bash 4+):

mapfile -t vids < <(shuf -e "${vids[@]}")

Or in older versions of Bash you could use good old-fashioned while loop:

vids2=()
while read -r item; do
    vids2+=("$item")
done < <(shuf -e "${vids[@]}")



回答2:


@janos has already explained the problem, so I won't duplicate that. But there is another approach to solving the problem: shuffle the array indexes (which are just numbers) rather than the entries themselves, and then copy elements into a new array in the shuffled order:

shuffledvids=()
for index in $(shuf -e "${!vids[@]}"); do    # The ! gets the indexes, rather than entries
    shuffledvids+=("${vids[index]}")
done
prinf '%s\n' "${shuffledvids[@]}"    # Another way to print array elements, one per line


来源:https://stackoverflow.com/questions/53737113/how-can-i-shuffle-an-array-of-filenames-that-have-spaces-in-them

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!