仅使用 bash 从目录中抓取随机文件
Grab random files from a directory using just bash
我想创建一个 bash 脚本,它可以抓取符合特定 glob 模式的文件并将它们复制到另一个文件夹,例如
$foo\
a.txt
b.txt
c.txt
e.txt
f.txt
g.txt
运行 请求 2 个文件的脚本我会得到
$bar\
c.txt
f.txt
我不确定 bash 是否有随机数生成器以及如何使用它从列表中提取。该目录也很大(超过 100K),因此一些 glob 内容将不起作用。
提前致谢
试试这个:
#!/bin/bash
sourcedir="files"
# Arguments processing
if [[ $# -ne 1 ]]
then
echo "Usage: random_files.bash NUMBER-OF-FILES"
echo " NUMBER-OF-FILES: how many random files to select"
exit 0
else
numberoffiles=""
fi
# Validations
listoffiles=()
while IFS='' read -r line; do listoffiles+=("$line"); done < <(find "$sourcedir" -type f -print)
totalnumberoffiles=${#listoffiles[@]}
# loop on the number of files the user wanted
for (( i=1; i<=numberoffiles; i++ ))
do
# Select a random number between 0 and $totalnumberoffiles
randomnumber=$(( RANDOM % totalnumberoffiles ))
echo "${listoffiles[$randomnumber]}"
done
- 用文件名构建数组
- 从 0 到数组大小的随机数
- 显示该索引处的文件名
- 如果你想随机 select 多个文件
,我内置了一个循环
- 你可以为文件的位置设置另一个参数,我在这里硬编码了。
另一种方法,如果由于同一目录中的文件太多而失败,可以是:
#!/bin/bash
sourcedir="files"
# Arguments processing
if [[ $# -ne 1 ]]
then
echo "Usage: random_files.bash NUMBER-OF-FILES"
echo " NUMBER-OF-FILES: how many random files to select"
exit 0
else
numberoffiles=""
fi
# Validations
find "$sourcedir" -type f -print >list.txt
totalnumberoffiles=$(wc -l list.txt | awk '{print }')
# loop on the number of files the user wanted
for (( i=1; i<=numberoffiles; i++ ))
do
# Select a random number between 1 and $totalnumberoffiles
randomnumber=$(( ( RANDOM % totalnumberoffiles ) + 1 ))
sed -n "${randomnumber}p" list.txt
done
/bin/rm -f list.txt
- 构建文件列表,使每个文件名都在一行上
- select一个随机数
- 在那一个中,随机数必须为 +1,因为行数从 1 开始,而不是像在数组中那样从 0 开始。
- 使用
sed
打印文件列表中的随机行
使用 GNU shuf
,这会将给定源目录中与给定 glob 模式匹配的 N 个随机文件复制到给定目标目录。
#!/bin/bash -e
shopt -s failglob
n=${1:?} glob=${2:?} source=${3:?} dest=${4:?}
declare -i rand
IFS=
[[ -d "$source" ]]
[[ -d "$dest" && -w "$dest" ]]
cd "$dest"
dest=$PWD
cd "$OLDPWD"
cd "$source"
printf '%s[=10=]' $glob |
shuf -zn "$n" |
xargs -0 cp -t "$dest"
像这样使用:
./cp-rand 2 '?.txt' /source/dir /dest/dir
这适用于包含数千个文件的目录。 xargs
将管理像 ARG_MAX
.
这样的限制
$glob
,未加引号,进行文件名扩展(glob 扩展)。因为 IFS
是空的,所以 glob 模式可以包含空格。
匹配sub-directories将导致cp
出错并过早退出(某些文件可能已被复制)。 cp -r
允许 sub-directories.
cp -t target
和 xargs -0
不是 POSIX.
请注意,对列表中的 select 个文件使用随机数会导致重复,因此您复制的文件可能少于 N 个。因此使用 GNU shuf
.
我想创建一个 bash 脚本,它可以抓取符合特定 glob 模式的文件并将它们复制到另一个文件夹,例如
$foo\
a.txt
b.txt
c.txt
e.txt
f.txt
g.txt
运行 请求 2 个文件的脚本我会得到
$bar\
c.txt
f.txt
我不确定 bash 是否有随机数生成器以及如何使用它从列表中提取。该目录也很大(超过 100K),因此一些 glob 内容将不起作用。
提前致谢
试试这个:
#!/bin/bash
sourcedir="files"
# Arguments processing
if [[ $# -ne 1 ]]
then
echo "Usage: random_files.bash NUMBER-OF-FILES"
echo " NUMBER-OF-FILES: how many random files to select"
exit 0
else
numberoffiles=""
fi
# Validations
listoffiles=()
while IFS='' read -r line; do listoffiles+=("$line"); done < <(find "$sourcedir" -type f -print)
totalnumberoffiles=${#listoffiles[@]}
# loop on the number of files the user wanted
for (( i=1; i<=numberoffiles; i++ ))
do
# Select a random number between 0 and $totalnumberoffiles
randomnumber=$(( RANDOM % totalnumberoffiles ))
echo "${listoffiles[$randomnumber]}"
done
- 用文件名构建数组
- 从 0 到数组大小的随机数
- 显示该索引处的文件名
- 如果你想随机 select 多个文件 ,我内置了一个循环
- 你可以为文件的位置设置另一个参数,我在这里硬编码了。
另一种方法,如果由于同一目录中的文件太多而失败,可以是:
#!/bin/bash
sourcedir="files"
# Arguments processing
if [[ $# -ne 1 ]]
then
echo "Usage: random_files.bash NUMBER-OF-FILES"
echo " NUMBER-OF-FILES: how many random files to select"
exit 0
else
numberoffiles=""
fi
# Validations
find "$sourcedir" -type f -print >list.txt
totalnumberoffiles=$(wc -l list.txt | awk '{print }')
# loop on the number of files the user wanted
for (( i=1; i<=numberoffiles; i++ ))
do
# Select a random number between 1 and $totalnumberoffiles
randomnumber=$(( ( RANDOM % totalnumberoffiles ) + 1 ))
sed -n "${randomnumber}p" list.txt
done
/bin/rm -f list.txt
- 构建文件列表,使每个文件名都在一行上
- select一个随机数
- 在那一个中,随机数必须为 +1,因为行数从 1 开始,而不是像在数组中那样从 0 开始。
- 使用
sed
打印文件列表中的随机行
使用 GNU shuf
,这会将给定源目录中与给定 glob 模式匹配的 N 个随机文件复制到给定目标目录。
#!/bin/bash -e
shopt -s failglob
n=${1:?} glob=${2:?} source=${3:?} dest=${4:?}
declare -i rand
IFS=
[[ -d "$source" ]]
[[ -d "$dest" && -w "$dest" ]]
cd "$dest"
dest=$PWD
cd "$OLDPWD"
cd "$source"
printf '%s[=10=]' $glob |
shuf -zn "$n" |
xargs -0 cp -t "$dest"
像这样使用:
./cp-rand 2 '?.txt' /source/dir /dest/dir
这适用于包含数千个文件的目录。
这样的限制xargs
将管理像ARG_MAX
.$glob
,未加引号,进行文件名扩展(glob 扩展)。因为IFS
是空的,所以 glob 模式可以包含空格。匹配sub-directories将导致
cp
出错并过早退出(某些文件可能已被复制)。cp -r
允许 sub-directories.cp -t target
和xargs -0
不是 POSIX.请注意,对列表中的 select 个文件使用随机数会导致重复,因此您复制的文件可能少于 N 个。因此使用 GNU
shuf
.