2009-10-30 43 views
70

Tôi đã hy vọng:Bash: Sao chép tên file một cách đệ quy, duy trì cấu trúc thư mục

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

sẽ mang lại một cấu trúc đối xứng trong dir điểm:

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

nhưng thay vào đó, cả hai tập tin được sao chép vào/tmp/gói. Một bản sao phẳng. (Đây là trên OSX).

Có một hàm bash đơn giản mà tôi có thể sử dụng để sao chép tất cả các tệp, bao gồm các tệp được chỉ định bằng ký tự đại diện (ví dụ: src/*. Js) vào đúng vị trí của chúng trong thư mục đích hay không. Một chút giống như "cho mỗi tập tin, chạy mkdir -p $(dirname "$file"); cp "$file" $(dirname "$file")", nhưng có lẽ một lệnh duy nhất.

This is a relevant thread, which suggests it's not possible. Giải pháp của tác giả không quá hữu ích đối với tôi, vì tôi chỉ muốn cung cấp danh sách tệp, ký tự đại diện hoặc không và sao chép tất cả chúng vào thư mục đích. IIRC MS-DOS xcopy làm điều này, nhưng có vẻ là không tương đương với cp.

Trả lời

111

Bạn đã thử sử dụng tùy chọn --parents? Tôi không biết liệu OS X có hỗ trợ điều đó, nhưng nó hoạt động trên Linux.

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

Nếu điều đó không làm việc trên OS X, hãy thử

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

như aif gợi ý.

+0

ok vì vậy tôi đã nói quá sớm. tôi thích câu trả lời này tốt nhất. – EMPraptor

+3

cảm ơn. hóa ra "cp --parents" là không thể trên mac, nhưng nó là tốt đẹp để biết cờ cho unixen khác. rsync -R là giải pháp di động đơn giản nhất cho vấn đề này. – mahemoff

+1

Tôi chấp nhận điều này cho sự sang trọng/ghi nhớ, nhưng chỉ phát hiện ra điều này không sao chép toàn bộ thư mục (trên OSX ít nhất), trong khi tar một dưới đây không. – mahemoff

20

Một cách:

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

oh, tôi thích điều này tốt hơn nhiều so với câu trả lời của tôi. – EMPraptor

+3

Bạn cũng có thể sử dụng tùy chọn '-C' để thực hiện chdir cho bạn -' tar cf - _files_ | tar -C/dest xf -' hoặc một cái gì đó như thế. –

+0

cảm ơn, điều này là ngắn gọn, mặc dù tôi thích rsync cho sự đơn giản. – mahemoff

1

Hãy thử ...

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

để cho những gì bạn đã làm ban đầu ...

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

hoặc

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

Hoặc, nếu bạn là trường học cũ, hãy sử dụng cpio:

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

Rõ ràng, bạn có thể lọc danh sách tệp thành nội dung trái tim của bạn.

Tùy chọn '-p' dành cho chế độ 'truyền qua' (như đối với '-i' cho đầu vào hoặc '-o' cho đầu ra). '-v' là chi tiết (liệt kê các tệp khi chúng được xử lý). '-m' bảo tồn thời gian sửa đổi. '-B' có nghĩa là sử dụng 'các khối lớn' (nơi các khối lớn là 5120 byte thay vì 512 byte); có thể nó không có hiệu lực trong những ngày này.

+0

câu trả lời tốt nhất để lọc! cảm ơn – milkplus

13

rsync's -R option sẽ làm những gì bạn mong đợi. Nó là một máy photocopy tập tin rất giàu tính năng.Ví dụ:

$ 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 

Mẫu kết quả:

$ find /tmp/package 
/tmp/package 
/tmp/package/images 
/tmp/package/images/icon.jpg 
/tmp/package/src 
/tmp/package/src/prog.js 
Các vấn đề liên quan