各ディレクトリのファイルをサイズで並べ替えてから、ディレクトリ形式(下)を維持しながら、最大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
(すべての実装が-v
verboseをサポートしているわけではありません。実装がそれをサポートしていない場合は置き換えてください。)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
find
指定されたファイルを見つけます"$dir"
。これには引用符を使用する必要があります。また、すべてのファイルで動作してdu
サイズを取得します。sort
結果をサイズで並べ替えます。head
最初の2つに制限されます。sed
ファイル名の前のサイズ値を削除します。xargs
パイプラインのパラメータを使用して実際のコマンドを構築します。
NUL区切り文字は通常、すべてのコマンドに表示される必要があるため、、および;z
フラグが使用されます。とのスイッチによって生成されます。sort
head
sed
0
du
xargs
-print0
find
-T
(なぜ私はそのフラグを使うのかわかりませんcp
。私の例ではそのフラグはありませんが、-v
フィードバックを提供するためです)。
答え3
コードには2つの問題があります。
- 出力を解析するのではなく、
ls
代わりにstat
以下を使用してください。 - ファイルが「多い」場合、またはファイル名に「面白い」文字( "
/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