tra-loi-cau-hoi-phat-trien-web.com

Làm cách nào để hợp nhất một thư mục vào thư mục khác bằng Bash?

Tôi đang tìm kiếm tập lệnh Shell hợp nhất các tệp từ thư mục này sang thư mục khác.

Mẫu vật:

html/
  a/
    b.html
  index.html

html_new/
  a/
    b2.html
    b.html

Sử dụng:

./mergedirs.sh html html_new

Kết quả:

html/
  a/
    b.html
    b2.html
  index.html

html/a/b.html đã được thay thế bằng html_new/a/b.html
[.__.] html/a/b2.html đã được sao chép từ html_new/a/b2.html
[.__.] html/index.html được giữ nguyên

68
NVI

Có lẽ bạn chỉ muốn cp -R $1/* $2/ - đó là một bản sao đệ quy.

(Nếu có thể có các tệp bị ẩn (những tệp có tên bắt đầu bằng dấu chấm), bạn nên đặt tiền tố lệnh đó bằng shopt -s dotglob; để chắc chắn rằng họ được khớp.)

76
Luke Maurer
cp -RT source/ destination/

Tất cả các tệp và thư mục trong source sẽ kết thúc bằng destination. Ví dụ, source/file1 sẽ được sao chép vào destination/file1.

Các -T cờ dừng source/file1 từ bị sao chép sang destination/source/file1 thay thế.

77
Flimm

Hãy xem rsync

rsync --recursive html/ html_new/

Rsync có rất nhiều cờ để thiết lập, vì vậy hãy xem trang web rsync để biết chi tiết

16
CarlG

Chỉ cần sử dụng rsync - đó là một công cụ tuyệt vời để sao chép và hợp nhất tệp cục bộ bên cạnh việc sao chép từ xa.

rsync -av /path/to/source_folder/ /path/to/destination_folder/

Lưu ý rằng dấu gạch chéo trên thư mục nguồn là cần thiết để chỉ sao chép nội dung của source_folder vào đích. Nếu bạn bỏ nó đi, nó sẽ sao chép source_folder đó là nội dung, đây có thể không phải là thứ bạn đang tìm kiếm vì bạn muốn hợp nhất các thư mục.

6
Gavster

Sẽ không cp -r công việc?

cp -r html_new/* html

hoặc (vì phiên bản đầu tiên sẽ không sao chép các tệp ".s Something")

cd html_new; cp -r . ../html

Xin lưu ý rằng -rđọc từ ống nếu bất kỳ tệp nào trong thư mục được sao chép là ống. Để tránh điều đó, hãy sử dụng -R thay thế.

2
DVK
cd html
cp -r . /path/to/html_new
2
Brian Clapper

Mặc dù câu hỏi này và câu trả lời được chấp nhận của nó là cổ xưa, tôi vẫn thêm câu trả lời của mình vì những câu hỏi hiện có sử dụng cp hoặc không xử lý một số trường hợp Edge hoặc yêu cầu làm việc tương tác. Thường thì trường hợp Edge/kịch bản/tính di động/nhiều nguồn không quan trọng, trong trường hợp nào tính đơn giản sẽ thắng và tốt hơn là sử dụng trực tiếp cp với ít cờ hơn (như trong các câu trả lời khác) để giảm tải nhận thức - nhưng đối với những lần lần khác (hoặc đối với chức năng có thể tái sử dụng mạnh mẽ) thì chức năng/lệnh này rất hữu ích và tình cờ không phải là bash cụ thể (tôi nhận ra câu hỏi này là về bash, vì vậy đó chỉ là một phần thưởng trong trường hợp này). Một số cờ có thể được viết tắt (ví dụ: với -a), nhưng tôi đã bao gồm tất cả rõ ràng ở dạng dài (ngoại trừ -R, xem bên dưới) để giải thích. Rõ ràng chỉ cần xóa bất kỳ cờ nào nếu có một số tính năng cụ thể mà bạn không muốn muốn (hoặc bạn đang sử dụng hệ điều hành không phải là posix hoặc phiên bản cp không xử lý cờ đó - Tôi đã thử nghiệm điều này trên GNU coreutils 8.25 'cp):

mergedirs() {
    _retval=0
    _dest="$1"
    shift
    yes | \
        for _src do
            cp -R --no-dereference --preserve=all --force --one-file-system \
                  --no-target-directory "${_src}/" "$_dest" || { _retval=1; break; }
        done 2>/dev/null
    return $_retval
}

mergedirs destination source-1 [source-2 source-3 ...]

Giải trình:

  • -R: có ngữ nghĩa tinh tế khác với -r/--recursive trên một số hệ thống (đặc biệt liên quan đến các tệp đặc biệt trong thư mục nguồn) như được giải thích trong câu trả lời này
  • --no-dereference: không bao giờ theo các liên kết tượng trưng trong NGUỒN
  • --preserve=all: giữ nguyên các thuộc tính được chỉ định (mặc định: chế độ, quyền sở hữu, dấu thời gian), nếu có thể các thuộc tính bổ sung: bối cảnh, liên kết, xattr, tất cả
  • --force: nếu không thể mở tệp đích hiện tại, hãy xóa tệp đó và thử lại
  • --one-file-system: ở lại trên hệ thống tập tin này
  • --no-target-directory: coi DEST như một tệp bình thường (được giải thích trong câu trả lời này , cụ thể là: If you do a recursive copy and the source is a directory, then cp -T copies the content of the source into the destination, rather than copying the source itself.)
  • [đầu vào đường ống từ yes]: ngay cả với --force, trong chế độ đệ quy cụ thể này cp vẫn hỏi trước khi ghi đè từng tệp, vì vậy chúng tôi đạt được tính không tương tác bằng cách chuyển đầu ra từ yes sang nó
  • [đầu ra đường ống đến /dev/null]: đây là để làm im lặng chuỗi câu hỏi lộn xộn dọc theo dòng cp: overwrite 'xx'?
  • [return-val & exit exit]: điều này đảm bảo vòng lặp thoát ngay khi có một bản sao bị lỗi và trả về 1 nếu có lỗi

BTW:

  • Một cờ mới thú vị mà tôi cũng sử dụng với điều này trên hệ thống của mình là --reflink=auto để thực hiện cái gọi là "bản sao ánh sáng" (sao chép trên ghi, với cùng lợi ích tốc độ như liên kết cứng và cùng kích thước có lợi cho đến khi và tỷ lệ nghịch với số lượng tệp phân kỳ trong tương lai). Cờ này được chấp nhận trong gần đây GNU cp và thực hiện nhiều hơn các hệ thống tập tin tương thích trên các nhân Linux gần đây. YMWV-a-lot trên các hệ thống khác.
2
Rowan Thorpe