Làm thế nào để di chuyển và tạo lại một thư mục cùng một lúc?


9

Tôi có một thư mục được gọi statisticstrong một máy chủ Ubuntu trong đó các tệp dữ liệu được lưu trữ thường xuyên. Làm cách nào tôi có thể đổi tên statisticsthư mục thành backup-xxtrong khi tạo lại statisticsthư mục có sẵn để lưu trữ các tệp mới?

Các tập tin trong statisticsthư mục được tạo bởi PHP file_put_contents.

Tôi thích đổi tên thư mục, vì có nhiều tệp trong statisticsthư mục.


Lúc đầu tôi nghĩ bạn có nghĩa là "cùng một lúc" rằng hoạt động nên là "nguyên tử" (càng xa càng tốt).
phk

@phk Vâng, đó chính xác là những gì tôi muốn nói.
Googlebot

Thuật ngữ chính xác sẽ là "thư mục" chứ không phải "thư mục".
Berk Özbalcı

Câu trả lời:


7
mv statistics backup-xx && mkdir statistics

Điều này sẽ đổi tên statisticsthư mục hiện có thành backup-xx, và nếu thành công, nó sẽ tiếp tục để tạo một statisticsthư mục mới .

Đối với một hoạt động nguyên tử hơn, hãy xem xét việc tạo một thư mục statistics-001(hoặc tương tự, có thể bằng cách thay thế 001bằng ngày hôm nay theo một định dạng phù hợp) và một liên kết tượng trưng đến nó được gọi là statistics:

mkdir statistics-001
ln -s statistics-001 statistics

Khi bạn muốn "xoay" cái này để dữ liệu mới đi vào một thư mục sạch, hãy tạo thư mục trước, sau đó tạo lại statisticsliên kết đến nó:

mkdir statistics-002
ln -sf statistics-002 statistics

mv statistics-001 backup-001

Bằng cách này, bất kỳ chương trình nào ghi vào statisticsthư mục (tức là thư mục mà liên kết tượng trưng này trỏ tới) sẽ không bao giờ 1 lần tìm thấy nó.

Nếu bạn cần các quyền đặc biệt hoặc quyền sở hữu được đặt trên thư mục statisticstrỏ đến, hãy đặt các quyền này trước khi (lại) tạo liên kết.

1 Hay đúng hơn, theo cách này, thời gian mà một chương trình sẽ không có thư mục đích hợp lệ được giảm thiểu tối đa có thể bằng các công cụ Unix tiêu chuẩn.


1
Bạn cũng có thể muốn chown --reference=backup-xx statistics ; chmod --reference=backup-xx statisticsthiết lập quyền sở hữu và quyền. Lý tưởng bạn sẽ làm điều này trước khi đổi tên, vì vậy một mkdir new ; chown ; chmod ; mv stats backup ; mv new statsquá trình loại.
Stephen Harris

@StephenHarris Vâng, trên các hệ thống có các cờ đó.
Kusalananda

Đây không phải là nguyên tử, mặc dù. Nó gần với nguyên tử, nhưng không hoàn toàn.
CVn

@ MichaelKjorling Đã sửa nó.
Kusalananda

ln -sfkhông phải là nguyên tử. Nó được chỉ định để hủy liên kết symlink cũ sau đó tạo một liên kết mới, nhất thiết phải là phi nguyên tử. Thay vào đó, bạn phải tạo một liên kết tượng trưng tạm thời bổ sung và sử dụng renamechức năng ( mvchẳng hạn như thông qua lệnh) để thay thế nguyên bản cũ. Xem cách tiếp cận của tôi ở đây: git.musl-libc.org/cgit/musl/tree/tools/,
R .. GitHub DỪNG GIÚP ICE

12

Không có cách nào để nguyên tử thay thế một thư mục bằng cách thư mục khác. Bạn có thể di chuyển thư mục cũ sau đó tạo một thư mục mới:

mv statistics backup-xx
mkdir statistics

Nhưng điều này để lại một cửa sổ nhỏ thời gian statisticskhông tồn tại. Đây là một vấn đề nếu một số quá trình có thể thả các tập tin trong thư mục bất cứ lúc nào.

Để thay thế một cách hiệu quả một thư mục, bạn cần sử dụng các liên kết tượng trưng. Tạo một thư mục có tên bao gồm khoảng thời gian từ đầu:

mkdir "statistics-$(date +%Y%m%d)"

(hoặc tuy nhiên bạn muốn chọn quy ước đặt tên thư mục). Tạo một liên kết tượng trưng với một tên cố định đến vị trí hiện tại:

ln -s  statistics

Để thay thế thư mục, trước tiên hãy tạo một thư mục mới và một liên kết tượng trưng mới, sau đó di chuyển nó để ghi đè lên liên kết tượng trưng cũ. Lưu ý rằng không một đồng bằng nào mvtrên liên kết tượng trưng cũng không đơn giản ln -ssẽ làm điều này: họ sẽ tạo một mục trong thư mục đích. GNU coreutils ln -snfcũng không phù hợp vì nó loại bỏ liên kết tượng trưng hiện có trước khi tạo một liên kết mới, để lại một cửa sổ thời gian nhỏ trong đó đường dẫn không tồn tại. Bạn có thể sử dụng GNU coreutils mv -Ttrên liên kết tượng trưng mới.

new_dir="statistics-$(date +%Y%m%d)"
mkdir "$new_dir"
ln -s statistics.new
mv -Tf statistics.new statistics

busybox' ln -sfcũng không phải là nguyên tử, tôi không biết về bất kỳ triển khai nào.
phk

1
Bên cạnh các liên kết nhận xét của phk cũng không an toàn 100% vì một quy trình đang chạy vẫn có thể có một mô tả tệp thư mục mở (đích liên kết tượng trưng) và nó có thể tạo thêm các tệp mới trong thư mục được đổi tên (nghĩ về openat()hoặc CWD). Tôi sẽ chỉ di chuyển nội dung của thư mục sang một cái mới. Điều đó vẫn không an toàn đối với các tệp đang mở, nhưng tốt hơn một chút. Trong nghi ngờ sử dụng logrotatemà nên tôn trọng các vấn đề như vậy tốt nhất có thể.
rudimeier

1
@phk Cuộc symlinkgọi hệ thống sẽ không ghi đè lên một tệp hiện có, vì vậy không thể chuyển trực tiếp một liên kết tượng trưng về mặt nguyên tử. Cuộc renamegọi hệ thống sẽ ghi đè lên một tệp hiện có, nhưng thật khó chịu là không có cách di động nào để thực hiện nó trong trình bao; có thể với GNU coreutils nhờ vào -Ttùy chọn.
Gilles 'SO- ngừng trở nên xấu xa'

3

Đừng đổi tên thư mục. Bạn nói rằng bạn thích đổi tên thư mục vì nó có rất nhiều tệp. Lý do duy nhất tôi có thể nghĩ rằng bạn muốn điều này là vì việc sao chép các tệp sẽ mất quá nhiều thời gian. Tuy nhiên, việc di chuyển (tức là đổi tên) các tệp là tức thời miễn là chúng được di chuyển đến một vị trí trên cùng một hệ thống tệp. Tôi cho rằng đây là điều bạn không nên làm vì nếu bạn thay đổi hệ thống tệp, mvsẽ mất nhiều thời gian cpcho dù nó có di chuyển thư mục hay nội dung của nó hay không.

Vì vậy, chỉ cần làm:

mkdir backup-xx && mv statistics/* backup-xx

Nếu bạn cũng cần lấy các tập tin ẩn, bạn có thể làm:

mkdir backup-xx && mv statistics/* statistics/.* backup-xx

Hoặc, nếu sử dụng bash:

shopt -s dotglob; mkdir backup-xx && mv statistics/* statistics/.* backup-xx

Bằng cách này, thư mục luôn ở đó nhưng bạn vẫn di chuyển nội dung của nó trong một thao tác đơn giản và nhanh chóng.


1

Bạn có thể di chuyển nội dung của thư mục thống kê sang thư mục mới được tạo thay vì tự di chuyển thư mục. Nếu bạn di chuyển toàn bộ thư mục thì bạn sẽ phải chạy một lệnh khác để thay đổi quyền của thư mục.

mkdir -p <path>/backup-xxx
mv statistics/* <path>/backup-xxx/.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.