随机选择文件夹中 30% 的文件

hav*_*kok 0 ls bash pipe

我有许多文件夹,每个文件夹中都有音频文件。我想挑出每个文件的 30% 并将它们(不是复制)剪切到另一个文件夹。鉴于我知道每个文件夹中的文件数,我可以看到这篇文章可以帮助我做到这一点。可悲的是,数字可能会改变,我想要一个可以做到这一点的管道 bash 线。这可能吗?如何选择 30% 的文件并将它们剪切到另一个文件夹?

Sté*_*las 5

使用bash4.4+ 和 GNU 系统,您可以执行以下操作:

readarray -td '' files < <(
  shopt -s nullglob dotglob
  printf '%s\0' * | sort -Rz
)
Run Code Online (Sandbox Code Playgroud)

$files用当前目录中所有文件的无序列表填充数组。

然后您可以使用以下内容移动其中的 30%:

echo mv -- "${files[@]:0:${#files[@]}*30/100}" /target/directory/
Run Code Online (Sandbox Code Playgroud)

(删除echo当你满意时它会做你想做的事)。

zshshell 中的等效项可能类似于:

files=(*(NDnoe['REPLY=$RANDOM']))
echo mv -- $files[1,$#files*30/100] /target/directory/
Run Code Online (Sandbox Code Playgroud)

这是相同的方法,只是更简洁,不需要外部实用程序。翻译:

  • shopt -s nullglob-> Nglob 限定符(当没有文件时创建一个空数组)。
  • shopt -s dotglob-> Dglob 限定符(不排除名称以点开头的文件)。
  • GNU sort -Rz:(noe['REPLY=$RANDOM']通过使用随机顺序排序来打乱列表)。
  • ${array[@]:offset:length}-> $array[first,last](zsh 现在也支持 Korn shell 语法,但我发现 zsh 更清晰)。
  • 随着bash我们使用NUL分隔的记录(-d ''/ -z/ \0),以便能够处理任意文件名。不需要它,zsh因为列表永远不会转换为单个字符串/流。