问题
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