Bash : 이름이 지정된 파일을 재귀 적으로 복사하여 폴더 구조를 유지합니다.


103

나는 바라고 있었다 :

cp -R src/prog.js images/icon.jpg /tmp/package

대상 디렉토리에 대칭 구조를 생성합니다.

/tmp
|
+-- package
    |
    +-- src
    |   |
    |   +-- prog.js
    |
    +-- images
        |
        +-- icon.jpg

대신 두 파일 모두 / tmp / package에 복사됩니다. 플랫 카피. (이것은 OSX에 있습니다).

와일드 카드 (예 : src / *. js)로 지정된 파일을 포함하여 모든 파일을 대상 디렉토리 내의 적절한 위치에 복사하는 데 사용할 수있는 간단한 bash 함수가 있습니까? "각 파일마다 실행 mkdir -p $(dirname "$file"); cp "$file" $(dirname "$file")"과 비슷하지만 단일 명령 일 수도 있습니다.

이것은 불가능하다는 것을 암시하는 관련 스레드입니다. 저자의 솔루션은 나에게 그다지 유용하지 않습니다. 와일드 카드 여부에 관계없이 파일 목록을 제공하고 모든 파일을 대상 디렉토리에 복사하기를 원하기 때문입니다. IIRC MS-DOS xcopy는 이것을 수행하지만 cp에 상응하는 것은없는 것 같습니다.

답변:


153

--parents 옵션을 사용해 보셨습니까? OS X이 지원하는지는 모르겠지만 Linux에서 작동합니다.

cp --parents src/prog.js images/icon.jpg /tmp/package

OS X에서 작동하지 않으면 시도해보십시오.

rsync -R src/prog.js images/icon.jpg /tmp/package

aif 제안대로.


4
감사. Mac에서는 "cp --parents"를 사용할 수 없지만 다른 유닉스의 플래그를 아는 것이 좋습니다. rsync -R은이 문제에 대한 가장 간단한 휴대용 솔루션입니다.
mahemoff 2009

1
나는 우아함 / 기억력을 위해 이것을 받아 들였지만 이것이 전체 디렉토리 (적어도 OSX에서)를 복사하지 않는 반면 아래의 tar는 복사하는 것을 발견했습니다.
mahemoff

cp --parentsOSX (BSD cp)에서 잘못된 옵션이지만 gcp(GNU cp)는 잘 작동합니다. 시스템에 아직없는 경우 brew install coreutils. U에는 g 접두사가있는 많은 유틸리티가 있습니다.
kyb

@mahemoff cp -R --parentsrsync -rR파일과 디렉토리를 상대적으로 복사합니다.
Vortico

22

일방 통행:

tar cf - <files> | (cd /dest; tar xf -)

오,이게 내 대답보다 훨씬 좋아.
EMPraptor

4
-C옵션을 사용하여 chdir을 수행 tar cf - _files_ | tar -C /dest xf -하거나 이와 비슷한 작업을 수행 할 수도 있습니다 .
D.Shawley

감사합니다. 간단하게 rsync를 선호하지만 이것은 간결합니다.
mahemoff 2009

1
큰! 아무도 이것을 쉘 명령으로 바꾸는 방법을 알고 있습니까? N 개의 입력을 받아 들여야하며 첫 번째 N-1은 복사 할 파일이고 마지막은 대상 폴더입니다.
arod

@arod $ {! #}는 마지막 매개 변수이며이를 사용하여 앞의 인수 stackoverflow.com/questions/1215538/… 을 가져옵니다 . 명령을 작성하는 경우 여기에서 요점에 링크하십시오.
mahemoff

18

또는 구식 인 경우 cpio를 사용합니다.

cd /source;
find . -print | cpio -pvdmB /target

분명히 파일 목록을 마음의 내용으로 필터링 할 수 있습니다.

'-p'옵션은 'pass-through'모드를위한 것입니다 (입력의 경우 '-i'또는 출력의 경우 '-o'에 대해). '-v'는 장황합니다 (파일이 처리되는대로 나열). '-m'은 수정 시간을 보존합니다. '-B'는 '빅 블록'사용을 의미합니다 (빅 블록은 512 바이트 대신 5120 바이트). 요즘에는 효과가 없을 가능성이 있습니다.


1
특수 문자 등으로 깨지지 않도록 옵션 -print0조합과 함께 사용 하는 것이 더 좋습니다 --null.find . -print0 | cpio -pvdmB --null /target
haridsv

구식이라고 부르고, 휴대용이라고 부르고, 무엇이든 부르지 만, cpio이 작업에 대해 확실히 신뢰 합니다. -print0-null옵션을 사용해야한다는 데 동의합니다. 그렇지 않으면 누군가 '특수 문자'(대부분 공백)가 포함 된 폴더를 제공하고 어떤 일이 발생할 것입니다. 개인적인 경험으로 말한 것은 아니지만 파일 이름에 공백이 있기 때문에 여러 파일을 백업하려고 할 때 절반 만 백업하게 될 수도 있습니다. (좋아, 나는 개인적인 경험에서 말하고있다.)
bballdave025

@ bballdave025 : cpio파일 이름에 줄 바꿈이 포함 된 경우 에만 문제가 발생합니다. 그러면 일반적으로 파일 이름의 각 줄 바꿈에 대해 두 개 이상의 파일 이름에 대한 오류 메시지가 표시됩니다. (때로는 더 적은 수의 메시지를받을 수 있지만 테스트 케이스를 구성 할 때 상당한주의가 필요합니다.). 를 사용할 때 옵션 cpio이 없었습니다 --null. 이중 대시 옵션은 SVR4 옵션 표기법의 일부가 아니 -print0었으며 의 개념도 find모두 존재하지 않았습니다 . 그러나 그것은 오래 전입니다 (예를 들어 90 년대 중반. Linux가 우위를 차지하기 전).
Jonathan Leffler

@Jonathan_Leffler의 세부 사항에 대해 감사드립니다. 여기서 배우는 것을 좋아합니다. 자, 나는 어떤 재귀 복사 실수를하여 공백 문제를 일으켰는지 기억하려고합니다. 그 실수를
저지

@ bballdave025 — 한 가지 가능성은 xargs혼합에서 사용 하는 것입니다. 공백, 탭, 줄 바꿈 등 공백으로 분할됩니다. OTOH, 어떻게 또는 왜 그렇게 할 것인지 모르겠습니다. cpio출력 모드 의 GNU manul은 한 줄에 하나의 파일 이름에 대해 명확합니다. SVR4 사용자 설명서 (1990 년 인쇄)는 모호합니다. cpio -o(복사 모드) 표준 입력을 읽어 경로 이름 목록을 얻고 해당 파일을 경로 이름 및 상태 정보와 함께 표준 출력에 복사합니다. 따라서 공백에서 이름이 깨질 가능성이 있습니다.
Jonathan Leffler

16

rsync의 -R 옵션 은 예상대로 수행합니다. 매우 기능이 풍부한 파일 복사기입니다. 예를 들면 :

$ rsync -Rv src/prog.js images/icon.jpg /tmp/package/
images/
images/icon.jpg
src/
src/prog.js

sent 197 bytes  received 76 bytes  546.00 bytes/sec
total size is 0  speedup is 0.00

샘플 결과 :

$ find /tmp/package
/tmp/package
/tmp/package/images
/tmp/package/images/icon.jpg
/tmp/package/src
/tmp/package/src/prog.js


1

시험...

for f in src/*.js; do cp $f /tmp/package/$f; done

그래서 당신이 원래했던 일을 위해 ...

for f in `echo "src/prog.js images/icon.jpg"`; do cp $f /tmp/package/$f; done

또는

v="src/prog.js images/icon.jpg"; for f in $v; do cp $f /tmp/package/$f; done

echo또는 $v여기 가 필요하지 않습니다 . 또한 대상에 해당 디렉토리가 없으면이 방법이 실패합니다.
Weijun Zhou
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.