复制均匀分布的文件子集

复制均匀分布的文件子集

例如我有文件:

file0.txt
file1.txt
file2.txt
....
file100.txt

我想在 bash 中复制 5 个文件,这将产生结果:

file0.txt
file19.txt
file39.txt
file59.txt
file79.txt

编辑。搞砸了计数应该是这样的:

file0.txt
file20.txt
file40.txt
file60.txt
file80.txt

因此文件是均匀间隔采样的。希望有一些很酷的oneliner。

答案1

请注意,大括号扩展不是通配符,无论结果中的单词是否引用实际文件,它都会扩展。如果您只想复制那些实际存在的文件,您可以这样做:

shopt -s failglob extglob
cp file@(0|[1357]9).txt  /path/to/destination/

在 中,您可以通过附加(对于 nullglob)限定符zsh来强制对任意字符串进行通配解释。(N)

cp file{0,{1..79..20}}.txt(N) /path/to/destination/

我们需要 nullglob 来避免错误任何的全局扩展无法匹配任何内容,但这意味着如果它们都不匹配,cp /path/to/destination/则将运行。那么严格来说,应该是:

(){ if (($#)) cp $@ /path/to/destination; } file{0,{19..79..20}}.txt(N)

或者使用以下方法(0|19|...)动态构造一个 glob:

() { cp file(${(~j[|])@}).txt /path/to/destination; } 0 {19..79..20}

这次没有 nullglob,所以你会得到正确的结果不匹配如果未找到文件,则会出现错误。

要每 20 到 5 个按数字排序的列表复制一个file<digits>.txt

() {
  printf -v argv '%s%20$.0s' $argv
  cp -- $argv[1,5] /path/to/destination
} file<->.txt(n)

答案2

bash 中的大括号扩展支持以下格式的步骤{<start>..<end>..<step>}

$ echo file{0..100..19}.txt
file0.txt file19.txt file38.txt file57.txt file76.txt file95.txt

虽然看起来你需要不规则的间距:

$ echo file0.txt file{19..100..20}.txt
file0.txt file19.txt file39.txt file59.txt file79.txt file99.txt

答案3

您提供的一组文件名(数字)中没有有用的模式,因此您可以期望的最简单的“一行”是:

cp file0.txt file19.txt file39.txt file59.txt file79.txt destination_dir/

我曾考虑过将间隔 0..100 除以 5,或者为每个增量添加 20,但是都没有给出您指定的文件集。

如果您不太确定想要哪一组文件,那么可以获取完整的 101 个文件集,将其除以所需的文件数量,然后沿着集合递增,选出目标文件。这是一个例子bash

files=(*)                                                 # Assume current directory
samples=5                                                 # How many required

total=${#files[@]}; echo total=$total                     # Number of files
interval=$(( total/samples )); echo interval=$interval    # Integer arithmetic

for ((i=0; i<samples; i++))
do
    fileNo=$((i*interval))                                # Which sample
    echo i=$i, fileNo=$fileNo, file=${files[$fileNo]}     # Chosen sample
    ## cp -- "${files[$fileNo]}" destination_dir/         # Copy the file
done

输出

total=101
interval=20
i=0, fileNo=0, file=file0.txt
i=1, fileNo=20, file=file26.txt
i=2, fileNo=40, file=file44.txt
i=3, fileNo=60, file=file62.txt
i=4, fileNo=80, file=file80.txt

正如您所看到的,所选文件与您所需的集不匹配,分别是file0.txtfile26.txtfile44.txtfile64,txtfile80.txt

答案4

如果您的系统已jot安装,它可以执行以下操作:

$ jot -w 'cp "file%d.txt" "destination/"' 5 0 100

该命令指示jot生成和5之间的数字(含)。每个数字都在打印规范的部分中被替换,因此,例如,如果您需要前导零,则可以使用0100%d-w... -w 'cp "file%03d.txt" ...

检查这些命令,如果它们看起来像您想要执行的操作,则向上箭头并将其通过管道传输到sh.

$ jot -w 'cp "file%d.txt" "destination/"' 5 0 100
cp "file0.txt" "destination/"
cp "file25.txt" "destination/"
cp "file50.txt" "destination/"
cp "file75.txt" "destination/"
cp "file100.txt" "destination/"
$ jot -w 'cp "file%d.txt" "destination/"' 5 0 100 | sh

相关内容