均一に分散されたファイルサブセットのコピー

均一に分散されたファイルサブセットのコピー

たとえば、次のファイルがあります。

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

したがって、ファイルは一定の間隔でサンプリングされます。素敵なオネライナーがありますように。

答え1

中括弧拡張はワイルドカードではなく、結果の単語が実際のファイルを参照しているかどうかに関係なく拡張されます。実際に存在するファイルのみをコピーするには、次のようにします。

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

では、zsh修飾子を追加して(nullglobの場合)、任意の文字列のワイルドカード解析を強制できます。(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|...)動的にグローブを設定します。

() { 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

指定したファイル名(数値)セットには便利なパターンがないため、期待できる最も簡単な「1行」は次のとおりです。

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.txt、、、file26.txtおよび)file44.txtと一致しません。file64,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

関連情報