가장 작은 파일을 먼저 복사 하시겠습니까?


15

재귀 적으로 복사하려는 하위 디렉토리와 파일을 포함하는 큰 디렉토리가 있습니다.

cp가장 작은 파일이 먼저 복사되도록 파일 크기 순서로 복사 작업을 수행해야한다는 것을 알려주 는 방법이 있습니까?


1
XY 문제 가 없는지 확인 하기 위해 왜 그렇게하는지 설명 할 수 있습니까?
goldilocks

4
@ TAFKA'goldilocks '-많은 비디오 파일이 있으며 각 디렉토리의 품질을 테스트하고 싶습니다. 가장 작은 비디오는 나머지 파일도 나쁜지 빠르게 알려줍니다.
nbubis

답변:


10

이것은 모든 하위 디렉토리에서 파일 이름 문제없이 단일 스트림으로 전체 작업을 한 번에 수행합니다. 모든 파일을 최소에서 최대로 복사합니다. mkdir ${DESTINATION}존재하지 않는 경우에 필요 합니다.

find . ! -type d -print0 |
du -b0 --files0-from=/dev/stdin |
sort -zk1,1n | 
sed -zn 's/^[^0-9]*[0-9]*[^.]*//p' |
tar --hard-dereference --null -T /dev/stdin -cf - |
    tar -C"${DESTINATION}" --same-order -xvf -

그래도 알아? 이것이 수행하지 않는 것은 자식 디렉토리입니다. 해당 파이프 라인을 통해 리디렉션을 수행 할 수는 있지만 경쟁 조건 일뿐입니다. 가장 단순 할 것입니다. 따라서 나중에이 작업을 수행하십시오.

find . -type d -printf 'mkdir -p "'"${DESTINATION}"'/%p"\n' |
    . /dev/stdin

또는 Gilles는 디렉토리 권한을 보존하기 위해 그의 대답에서 매우 좋은 지적을하기 때문에 시도해야합니다. 나는 이것이 그렇게 할 것이라고 생각한다.

find . -type d -printf '[ -d "'"${DESTINATION}"'/%p" ] || 
    cp "%p" -t "'"${DESTINATION}"'"\n' |
. /dev/stdin

mkdir어쨌든 보다 더 빨리 기꺼이 내기를 할 것 입니다.


1
젠장, 마이크 서브! +1
goldilocks

3
@ TAFKA'goldilocks '칭찬으로 받아들입니다. 매우 감사합니다.
mikeserv

15

사용하는 빠르고 더러운 방법은 다음과 같습니다 rsync. 이 예제에서는 10MB 미만의 것을 "작은"것으로 간주합니다.

먼저 작은 파일 만 전송하십시오.

rsync -a --max-size=10m srcdir dstdir

그런 다음 나머지 파일을 전송하십시오. 이전에 전송 된 작은 파일은 수정하지 않으면 다시 복사되지 않습니다.

rsync -a srcdir dstdir

에서 man 1 rsync

   --max-size=SIZE
          This  tells  rsync to avoid transferring any file that is larger
          than the specified SIZE. The SIZE value can be suffixed  with  a
          string  to  indicate  a size multiplier, and may be a fractional
          value (e.g. "--max-size=1.5m").

          This option is a transfer rule, not an exclude,  so  it  doesnt
          affect  the  data  that  goes  into  the file-lists, and thus it
          doesnt affect deletions.  It just limits  the  files  that  the
          receiver requests to be transferred.

          The  suffixes  are  as  follows:  "K"  (or  "KiB") is a kibibyte
          (1024), "M" (or "MiB") is a mebibyte (1024*1024),  and  "G"  (or
          "GiB")  is  a gibibyte (1024*1024*1024).  If you want the multi
          plier to be 1000 instead of  1024,  use  "KB",  "MB",  or  "GB".
          (Note: lower-case is also accepted for all values.)  Finally, if
          the suffix ends in either "+1" or "-1", the value will be offset
          by one byte in the indicated direction.

          Examples:    --max-size=1.5mb-1    is    1499999    bytes,   and
          --max-size=2g+1 is 2147483649 bytes.

물론 파일 별 전송 순서는 최소에서 최대로 엄격하지는 않지만 요구 사항의 정신을 충족시키는 가장 간단한 솔루션 일 수 있습니다.


여기에 2 개의 하드 링크 사본이 ​​있고 소프트 링크는 각각 2 개의 사본에 대해 실제 파일로 변환됩니다. 당신은 훨씬 더 잘 --copy-dest=DIR하거나 --compare-dest=DIR생각합니다. 링크가 누락되어 답변을 게시 한 후 --hard-dereference본인 을 추가 해야하는 원인 만 알고 있습니다 tar. rsync어쨌든 다른 파일 시스템과 로컬 파일 시스템에 더 구체적으로 작동 한다고 생각 합니다 .USB 키와 함께 사용했으며 대역폭 제한을 설정하지 않으면 버스가 과도하게 사용됩니다. 나는 그 대신 다른 것을 사용해야한다고 생각합니다.
mikeserv

1
"빠르고 더러운 방법"은 +1입니다. 일반적으로 자동화 목적과 향후 유지 관리 가능성이 더 단순할수록 좋습니다. 나는 이것이 실제로 꽤 깨끗하다고 ​​생각합니다. "우아한"대 "kludgy"및 "견고한"대 "불안정한"은 때때로 디자인 목표와 충돌 할 수 있지만, 균형을 잡을 수있는 좋은 균형이 있으며, 이것이 우아 하고 상당히 강력 하다고 생각합니다 .
와일드 카드

4

아니 cp직접, 그 잘 자사의 능력을 넘어. 그러나 cp올바른 순서로 파일 을 호출하도록 정렬 할 수 있습니다 .

Zsh를 사용하면 glob 한정자를 사용하여 파일을 크기별로 정렬 할 수 있습니다 . 아래에서 아래 /path/to/source-directory로 크기가 커지는 파일을 복사하는 zsh 스 니펫이 있습니다 /path/to/destination-directory.

cd /path/to/source-directory
for x in **/*(.oL); do
  mkdir -p /path/to/destination-directory/$x:h
  cp $x /path/to/destination-directory/$x:h
done

루프 대신 zcp함수를 사용할 수 있습니다 . 그러나 대상 디렉토리를 먼저 작성해야하며 이는 암호화 된 oneliner에서 수행 할 수 있습니다.

autoload -U zmv; alias zcp='zmv -C'
cd /path/to/source-directory
mkdir **/*(/e\''REPLY=/path/to/destination-directory/$REPLY'\')
zcp -Q '**/*(.oL)' '/path/to/destination-directory/$f'

소스 디렉토리의 소유권을 유지하지 않습니다. 당신이 원하는 경우에, 당신은 같은 적절한 복사 프로그램을 입대해야 cpio하거나 pax. 그렇게하면 전화를 걸 cp거나 zcp추가 할 필요가 없습니다 .

cd /path/to/source-directory
print -rN **/*(^.) **/*(.oL) | cpio -0 -p /path/to/destination-directory

2

나는 cp -r이것을 직접 할 수있는 방법이 없다고 생각 합니다. 위저드 find/ awk솔루션 을 얻기까지는 시간이 불확실 할 수 있으므로 다음과 같은 간단한 펄 스크립트가 있습니다 :

#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);

use File::Find;
use File::Basename;

die "No (valid) source directory path given.\n"
    if (!$ARGV[0] || !-d -r "/$ARGV[0]");

die "No (valid) destination directory path given.\n"
    if (!$ARGV[1] || !-d -w "/$ARGV[1]");

my $len = length($ARGV[0]);
my @files;
find (
    sub {
        my $fpath = $File::Find::name;
        return if !-r -f $fpath;
        push @files, [
            substr($fpath, $len),
            (stat($fpath))[7],
        ]
    }, $ARGV[0]
);

foreach (sort { $a->[1] <=> $b->[1] } @files) {
    if ($ARGV[2]) {
        print "$_->[1] $ARGV[0]/$_->[0] -> $ARGV[1]/$_->[0]\n";
    } else {
        my $dest = "$ARGV[1]/$_->[0]";
        my $dir = dirname($dest);
        mkdir $dir if !-e $dir;
        `cp -a "$ARGV[0]/$_->[0]" $dest`;
    }
} 
  • 이것을 사용하십시오 : ./whatever.pl /src/path /dest/path

  • 인수는 모두 절대 경로 여야합니다 . ~또는 쉘이 절대 경로로 확장되는 다른 모든 것이 좋습니다.

  • 세 번째 인수 (리터럴 제외)를 추가하면 0복사하는 대신 바이트 크기의 파일 크기가 앞에 붙은 상태로 복사하여 수행 할 작업에 대한 보고서를 표준으로 인쇄합니다.

    4523 /src/path/file.x -> /dest/path/file.x
    12124 /src/path/file.z -> /dest/path/file.z

    크기별로 오름차순으로 표시됩니다.

  • cp34 행 의 명령은 문자 그대로의 쉘 명령이므로 스위치로 원하는 모든 작업을 수행 할 수 있습니다 (방금 -a모든 특성을 유지하는 데 사용 했습니다).

  • File::Find그리고 File::Basename, 두 핵심 모듈이다 그들은 펄의 모든 설치에서 사용할 수 있습니다 즉.


논란의 여지가 있지만 이것이 유일한 답입니다. 아니면 제목이 ... 방금 바뀌 었나요? 내 브라우저 창은 호출 cp - copy smallest files first?되었지만 게시물의 제목은 copy smallest files first?어쨌든 옵션은 결코 내 철학이 아닙니다. 그러나 여전히 당신과 David는 사용 된 유일한 사람 cp이며 당신은 그것을 뽑아 낸 유일한 사람입니다.
mikeserv

@mikeserv 내가 사용한 유일한 이유 cp는 (크로스 플랫폼 지향) perl에서 * nix 파일 특성을 유지하는 가장 간단한 방법이기 때문입니다. 브라우저 표시 줄에 표시되는 이유 cp - 는 (IMO goofy) SE 기능 때문입니다. 선택한 태그 중 가장 인기있는 태그가 실제 제목 앞에 표시됩니다.
goldilocks

그럼 칭찬을 철회합니다. 사실, 당신은 종종 pearl주변의 목공에서 나오는 것을 보지 못합니다 .
mikeserv

1

또 다른 옵션은 du의 출력에 cp를 사용하는 것입니다.

oldIFS=$IFS
IFS=''
for i in $(du -sk *mpg | sort -n | cut -f 2)
do
    cp $i destination
done
IFS=$oldIFS

이것은 여전히 ​​한 줄로 할 수는 있지만 읽을 수 있도록 분할했습니다.


적어도 $ IFS에 대해 뭔가 할 필요가 없습니까?
mikeserv

예 .. 파일 이름에 줄 바꿈이 없다고 가정합니다.
David Wilkins

1
이것은 OP가 설명한 디렉토리 계층을 통한 재귀를 처리하지 않는 것 같습니다.
cpugeniusmv

1
@cpugeniusmv 올바른 ... 어떻게 재귀 부분을 놓쳤습니다 ... 재귀를 처리하기 위해 이것을 수정할 수는 있지만이 시점에서 다른 대답이 더 나은 일을한다고 생각합니다. 질문을 보는 사람을 돕기 위해 여기에 남겨 두겠습니다.
David Wilkins

1
@DavidWilkins-이것은 많은 도움이됩니다.
nbubis
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.