我有一个具有这种性质的文件目录:
1985-08-28_state.txt 2001-04-29_state.txt 2016-12-29_state.txt
1985-08-29_state.txt 2001-04-30_state.txt 2016-12-30_state.txt
1985-08-30_state.txt 2001-05-01_state.txt 2016-12-31_state.txt
我想选择5月至6月的所有文件,然后从列表中随机选择一个文件。
#!/bin/bash -u
states_path=./daily_states/
date="*-05-*_state.txt *-06-*_state.txt" #Patterns for May-June files
statefile=`ls ${states_path}/$date| shuf -n 1`
printf "$statefile \n"
,但这不能访问第二个参数。
ls: cannot access *-06-*_state.txt: No such file or directory
为什么会这样,我该如何解决?
我愿意采取任何其他方式。
我想到了另一种方法。不是最优雅的解决方案。但是我想这行得通吗?
states_path=/daily_states/
statefile[0]=`ls ${states_path}/*-05-*_state.txt | shuf -n 1`
statefile[1]=`ls ${states_path}/*-06-*_state.txt | shuf -n 1`
randstate=$(($RANDOM % 2))
echo "${statefile[$randstate]}"
答案 0 :(得分:1)
让我们看看您的变量如何扩展。您设置:
date="*-05-*_state.txt *-06-*_state.txt"
然后使用命令输出设置$statefile
:
ls ${states_path}/*-05-*_state.txt *-06-*_state.txt| shuf -n 1
现在您看到问题了吗?
一种更好的处理方式可能是使用数组存储模式,而使用另一个数组收集文件名,因为parsing ls is problematic:
#!/usr/bin/env bash
states_path=./daily_states/
patterns=("*-05-*_state.txt" "*-06-*_state.txt")
a=() # initialize an empty array
shopt -s nullglob # if no expansion occurs, expand to null
# Step through your patterns...
for monthpat in "${patterns[@]}"; do
# And add files matching the pattern to the array.
a+=( $states_path/$monthpat )
done
# Print the list
declare -p a
# or if you prefer,
printf '%s\n' "${a[@]}"
# Or just print one random entry:
printf 'random: %s\n' "${a[ $(( $RANDOM % ${#a[@]} )) ]}"
请注意,我不使用shuf
,因为它不是bash的一部分,并且在使用bash的操作系统(FreeBSD和macOS)上不可用。
如果您知道只对这两个月的文件感兴趣,则可以将它们表示为一个文件。因此:
a=( $states_path/*-0[56]-*_state.txt )
printf '%s\n' "${a[$(($RANDOM%${#a[@]}))]}"
答案 1 :(得分:1)
您的简短解决方案存在一些问题:
ls
的输出。带有空格等的路径可能会引起问题。这里是解决这些问题的替代方法,而且更短:
shuf -en1 daily_states/*-05-*_state.txt daily_states/*-06-*_state.txt
两个小球也可以如下组合。
shuf -en1 daily_states/*-0{5,6}-*_state.txt
如ghoti所述,请考虑使用shopt -s nullglob
-比后悔更安全。