it-swarm-vi.com

Làm thế nào để ghi đè tập tin mục tiêu với mv?

Tôi có rất nhiều tệp và thư mục trong thư mục con tôi muốn chuyển đến thư mục mẹ. Đã có một số tệp và thư mục trong thư mục đích cần được ghi đè. Các tập tin chỉ hiện diện trong mục tiêu nên được giữ nguyên. Tôi có thể ép buộc mv để làm điều đó không? Nó (mv * ..) phàn nàn

mv: cannot move `xyz' to `../xyz': Directory not empty

Tôi đang thiếu gì?

175
EricSchaefer

Bạn sẽ phải sao chép chúng đến đích và sau đó xóa nguồn, sử dụng các lệnh cp -r * .. theo dõi bởi rm -rf *.

Tôi không nghĩ bạn có thể "hợp nhất" các thư mục bằng cách sử dụng mv.

128
dogbane

rsync có lẽ sẽ là một lựa chọn tốt hơn ở đây. Nó đơn giản như rsync -a subdir/ ./.

Cây thử nghiệm của tôi ở định dạng filename: contents:

./file1:root
./file2:root
./dir/file3:dir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

Đang chạy rsync:

$ rsync -a -v subdir/ ./
sending incremental file list
./
file1
dir/
dir/file3

Cung cấp:

./file1:subdir
./file2:root
./dir/file3:subdir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

Và sau đó, để mô phỏng mv, có lẽ bạn muốn xóa thư mục nguồn:

$ rm -r subdir/

Tặng:

./file1:subdir
./file2:parent
./dir/file3:subdir
./dir/file4:dir

Nếu điều này là sai, bạn có thể vui lòng cung cấp một ví dụ tương tự (ví dụ: sử dụng cây thử nghiệm của tôi từ gần đầu câu trả lời này) với kết quả mong muốn không?

77
Mikel

rsync có thể xóa nguồn sau khi sao chép bằng --remove-source-files tham số. Đây sẽ là một cách thuận tiện để làm những gì bạn muốn.

Từ rsync man page:

        --remove-source-files   sender removes synchronized files (non-dir)
52
Mike Chen

Bạn có thể làm điều này với cprm, nhưng không sao chép lượng dữ liệu khổng lồ mà bạn (có lẽ) đang cố gắng tránh chuyển. @mattdm đã ám chỉ điều này trong bình luận của anh ấymột câu trả lời cho câu hỏi khác có một cuộc thảo luận đầy đủ hơn về các tùy chọn khác nhau.

cp -rlf source destination
rm -r source

Về cơ bản, -l tùy chọn cho lệnh cp tạo liên kết cứng đến tệp thay vì sao chép dữ liệu của chúng sang tệp mới.

24
palswim

Đây là tập lệnh di chuyển tệp từ bên dưới /path/to/source/root đến đường dẫn tương ứng dưới /path/to/destination/root.

  • Nếu một thư mục tồn tại trong cả nguồn và đích, nội dung sẽ được di chuyển và hợp nhất theo cách đệ quy.
  • Nếu một tập tin hoặc thư mục tồn tại trong nguồn nhưng không ở đích, nó sẽ được di chuyển.
  • Bất kỳ tập tin hoặc thư mục đã tồn tại ở đích được để lại. (Đặc biệt các thư mục được hợp nhất được để lại trong nguồn. Điều này không dễ sửa.)

Cẩn thận, mã chưa được kiểm tra.

export dest='/path/to/destination/root'
cd /path/to/source/root
find . -type d \( -exec sh -c '[ -d "$dest/$0" ]' {} \; -o \
                  -exec sh -c 'mv "$0" "$dest/$0"' {} \; -Prune \) \
    -o -exec sh -c '
        if ! [ -e "$dest/$0" ]; then
          mv -f "$0" "$dest/$0";
        fi
' {} \;

Chủ đề này đã tồn tại trong nhiều năm và vẫn đứng thứ 1 trên google vì vậy tôi muốn thêm một phương pháp khác. Làm thế nào tôi thường làm điều này: đóng gói nội dung của thư mục con vào một tarball, di chuyển tarball lên thư mục cha và sau đó giải nén nó với hành vi --overwrite mặc định. Điều này thực hiện chính xác những gì bạn đang tìm kiếm. Sau đó, bạn có thể loại bỏ subir của bạn.

cd xyz
tar -cvzpf tmp.tar.gz *
mv tmp.tar.gz ../tmp.tar.gz
cd ..
tar -xvzpf tmp.tar.gz
rm -rf xyz
rm -f tmp.tar.gz
3
Simon Kraus

Nếu bạn có đủ dung lượng, bạn có thể thực hiện theo cách sau:

mv -bfv directory_1/* directory_2/ # all duplicate source files/directories 
                                   # will have ~ appended to them
find -name "*~" -delete            # will recursively find and delete all files 
                                   # with ~ on the end

Đảm bảo không có bất kỳ tệp quan trọng nào có dấu ~ ở cuối chúng, nhưng nếu có, bạn có thể thêm --suffix=whateveryouwant thay vì mặc định.

0
4D3H2