For 루프는 최대 크기의 파일을 찾아 다른 디렉터리에 복사합니다.

For 루프는 최대 크기의 파일을 찾아 다른 디렉터리에 복사합니다.

각 디렉터리의 파일을 크기별로 정렬한 다음 디렉터리 형식(아래)을 유지하면서 가장 큰 파일 두 개를 다른 위치에 복사하는 루프를 만들려고 합니다.

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  

저는 리눅스를 처음 접해서 어려움을 겪고 있습니다. 나는 시도했다:

#!/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

코드에 두 가지 문제가 있습니다.

  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

관련 정보