Forループは最大サイズのファイルを見つけて別のディレクトリにコピーします。

Forループは最大サイズのファイルを見つけて別のディレクトリにコピーします。

各ディレクトリのファイルをサイズで並べ替えてから、ディレクトリ形式(下)を維持しながら、最大2つのファイルを別の場所にコピーするループを作成しようとしています。

folder/sample 1  
       .../s1.fastq.gz  
       .../s2.fastq.gz  
       .../s3.fastq.gz  
       .../s4.fastq.gz  
folder/sample 2  
       .../s1.fastq.gz  
       .../s2.fastq.gz  
       .../s3.fastq.gz  
       .../s4.fastq.gz  

私はLinuxに初めて触れて苦労しています。私は試した:

#!/bin/bash
mkdir newfolder

for dir in folder/*
do
echo $dir
ls -S $dir/*.gz | head -n +2 | cp -T newfolder

done

ただし、次のエラーが発生します。

cp: missing destination file operand after 'newfolder.'

コピー機能に大容量ファイルを正しく供給する方法は?

xargsも試してみましたが、エラーが発生しました。

xargs: invalid option -- 'w'

一度に一室ずつ正しく供給していないからです。

答え1

zshシェルの場合は、以下より良い選択になりますbash

#! /bin/zsh -
ret=0
for dir (folder/*(/)) {
  two_largest_files=($dir/*.gz(N.OL[1,2]))
  if (($#two_largest_files)) {
    mkdir -p newfolder/$dir:t &&
      cp -v $two_largest_files newfolder/$dir:t/ || ret=$?
  }
}
exit $ret

(すべての実装が-vverboseをサポートしているわけではありません。実装がそれをサポートしていない場合は置き換えてください。)cp(set -x; cp $two...)

答え2

これは非常に複雑です。まず、ls名前に改行が含まれるファイルの場合、状況が複雑になる可能性があるため、出力を解析しないでください。したがって、すべてのパイプラインでレコード(行)区切り文字としてNULを使用することをお勧めします。例は次のとおりです。

for dir in folder/*
do
    echo "$dir"
    find "$dir" -type f -print0 -exec du -h0 {} + | sort -hrz | head -zn 2 |
        sed -z 's/^.*[[:space:]]// ' | xargs -0I@ cp -v @ newfolder
done
  1. find指定されたファイルを見つけます"$dir"。これには引用符を使用する必要があります。また、すべてのファイルで動作してduサイズを取得します。
  2. sort結果をサイズで並べ替えます。
  3. head最初の2つに制限されます。
  4. sedファイル名の前のサイズ値を削除します。
  5. xargsパイプラインのパラメータを使用して実際のコマンドを構築します。

NUL区切り文字は通常、すべてのコマンドに表示される必要があるため、、および;zフラグが使用されます。とのスイッチによって生成されます。sortheadsed0duxargs-print0find

-T(なぜ私はそのフラグを使うのかわかりませんcp。私の例ではそのフラグはありませんが、-vフィードバックを提供するためです)。

答え3

コードには2つの問題があります。

  1. 出力を解析するのではなく、ls代わりにstat以下を使用してください。
  2. ファイルが「多い」場合、またはファイル名に「面白い」文字( " /sample 1/")が含まれている場合とfindを使用しますxargs。詳しく見て知っman findてくださいman xargs

次のようにしてください。

mkdir newdir

find . -type f -name '*.gz' -print0 |\
  xargs -0 -r stat --printf="%s:%N" |\
  sort -rn |\
  head -n 2 |\
  cut -d: -f 2 |\
  xargs cp -T newdir

警告する!テストされていないコード(電話をかけています)。最後の行を次に置き換えます。

xargs echo cp -T newdir

それが働くまで。

気になる方は一度見てみてくださいhttps://mywiki.wooledge.org/ParsingLs

関連情報