Làm cách nào để tìm tập tin giữa hai ngày bằng cách sử dụng Tìm kiếm Tìm?


21

Tôi có một tài khoản email đã vượt qua 60GB email và hiện tại tôi đang gặp nhiều rắc rối khi sử dụng ứng dụng email để lưu trữ email của năm ngoái (2011).

Qua thiết bị đầu cuối, tôi đang cố gắng sử dụng find để xác định vị trí các tệp trong khoảng thời gian 2011-01-01 đến 2011-12-31, nhưng không có kết quả.

Làm thế nào tôi có thể tìm thấy các tập tin giữa hai ngày?

Nếu có liên quan, mục tiêu cuối cùng sẽ là một lô sẽ di chuyển từng tệp được tìm thấy, khớp với khoảng thời gian ngày, vào một thư mục.


@EliahKagan Vào thời điểm đó, nếu bộ nhớ phục vụ, các tên trùng lặp không phải là vấn đề. Tuy nhiên, nếu bạn cho rằng bạn có thời gian, thông tin bổ sung về bất kỳ chủ đề cụ thể nào luôn được đánh giá cao :) Ngoài ra, tôi đã bỏ phiếu cho câu trả lời của bạn vì nó cung cấp thêm thông tin chi tiết về chủ đề này.
Zuul

@EliahKagan Trong trường hợp đó, tôi khuyến khích bạn cung cấp câu trả lời với sự không an toàn thực tế mà bạn đã nêu bật :)
Zuul

Câu trả lời:


16

Bạn có thể sử dụng tập lệnh này:

#!/bin/bash
for i in $(find Your_Mail_Dir/ -newermt "2011-01-01" ! -newermt "2011-12-31"); do
  mv $i /moved_emails_dir/
done

6
Đầu ra của findkhông nên được xử lý trong một forvòng lặp shell như thế này, ngoại trừ khi nó được đảm bảo rằng không có tệp nào có bất kỳ khoảng trống nào trong tên của nó. -exec, -execdirhoặc -print0 | xargsthường nên được sử dụng thay thế; một giải pháp khả thi khác, thường ít được mong muốn hơn nhưng lại cho phép forsử dụng vòng lặp, là đặt tạm thời IFSđể một không gian không được công nhận là dấu tách trường.
Eliah Kagan

@EliahKagan vậy lệnh sẽ trông như thế nào sau đó: Chỉ cần thay thế findbằng exec? Bạn có phiền khi thêm một câu trả lời giải quyết việc sử dụng khoảng trắng .. ?? Nhiều đánh giá cao.
SherylHohman

3
@SherylHohman Không, đừng sử dụng execlệnh. Sử dụng một findlệnh với -exechành động để chạy mv, hoặc bất cứ điều gì bạn cần chạy, như được mô tả trong câu trả lời tôi đã đăng . Khi find... -execchạy lệnh của bạn với các tên đường dẫn nó tìm thấy, nó không sử dụng một lớp vỏ, vì vậy không gian không kích hoạt tách từ hoặc globbing . (Bạn có thể muốn đăng một câu hỏi mới về trường hợp cụ thể của mình hoặc hỏi chính xác những gì bạn muốn biết.)
Eliah Kagan

@EliahKagan Xin lỗi, tôi đã đọc sai bài đăng của bạn - và đó là từ bạn ! Bạn thật tuyệt vời! Bài viết của bạn rất tuyệt vời .. và cảm ơn vì đã phản hồi, mặc dù đó là lỗi của chính tôi khi đọc !!
SherylHohman

40

Bash tìm tập tin giữa hai ngày:

find . -type f -newermt 2010-10-07 ! -newermt 2014-10-08

Trả về danh sách các tệp có dấu thời gian sau 2010-10-07 và trước 2014-10-08

Bash tìm tập tin từ 15 phút trước cho đến bây giờ:

find . -type f -mmin -15

Trả về danh sách các tệp có dấu thời gian sau 15 phút trước nhưng trước đây.

Bash tìm tập tin giữa hai dấu thời gian:

find . -type f -newermt "2014-10-08 10:17:00" ! -newermt "2014-10-08 10:53:00"

Trả về các tệp có dấu thời gian giữa 2014-10-08 10:17:002014-10-08 10:53:00


10

Di chuyển các tệp và nhắc nhở người dùng khi có tên trùng lặp:

Như Subv3rsion củaEric Leschinski của câu trả lời cho thấy, các -newermtfile ngữ Selects sửa đổi gần đây hơn ngày (và thời gian không bắt buộc) quy định như toán hạng của nó. Để tìm tập tin

  • bất cứ nơi nào trong srcdir (nghĩa là, bao gồm cả thư mục con, thư mục con của họ, v.v.)
  • sửa đổi lần cuối vào (ví dụ) tháng 9 năm 2014
  • và chuyển chúng đếndestdir

...bạn có thể chạy:

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -i {} destdir/ \;

Trong một -execbiểu thức, find vượt qua tên tệp được tìm thấy thay cho {}. ;biểu thị -execrằng lệnh sẽ được chạy và tất cả các đối số của nó đã được cung cấp (trong trường hợp các biểu thức tiếp theo được chuyển qua để tìm sau các -execđối số của vị từ cụ thể đó - xem bên dưới để biết ví dụ về điều này). ;phải được thoát \;vì nó không được giải thích đặc biệt bởi vỏ. (Nếu không \, ;sẽ kết thúc toàn bộ findlệnh, hoạt động giống như một dòng mới. Mặc dù findlệnh này không có gì sau -execbiểu thức này , nhưng không vượt qua được; đối số vẫn là một lỗi cú pháp.)

Nếu bạn chỉ muốn liệt kê các tệp - điều này được khuyến khích nếu bạn không chắc chắn làm thế nào các email cũ được lưu trữ hoặc những tệp khác có thể có mặt - bỏ qua -execvà mọi thứ ở bên phải của nó. (Đối với email, thường các email từ các ngày khác nhau được lưu trữ trong cùng một tệp; đối với ai đó trong tình huống được mô tả trong câu hỏi ở đây, tôi khuyên bạn nên điều tra cách chúng được lưu trữ trước khi di chuyển bất kỳ tệp nào.) Nếu bạn muốn in cả tên của họ và di chuyển họ, thêm -printtrước -exec.

mv -i nhắc nhở bất cứ lúc nào một tập tin sẽ được ghi đè ở đích, chẳng hạn như sẽ xảy ra nếu:

  • một tệp cùng tên tồn tại từ bản sao lưu trước đó, hoặc
  • một tệp có cùng tên nhưng từ một thư mục con khác srcdirđã được di chuyển trong cùng một findhoạt động, hoặc
  • (ít có khả năng) một tệp cùng tên đã được tạo ở đâu đó trong srcdircùng một findhoạt động, sau khi bản gốc được di chuyển nhưng không bao lâu sẽ được tìm thấy một khi findđi qua một thư mục con khác.

Những cách khác để gọi rm :

Bạn có các tùy chọn khác về cách xử lý tệp có tên trùng lặp.

  • Nếu không có -i(nghĩa là ), thường sẽ không nhắc phê duyệt, nhưng sẽ làm như vậy nếu tệp đích là chỉ đọc. (mv {} destdir/mvmv đôi khi thậm chí có thể thành công trong việc ghi đè tệp chỉ đọc, chẳng hạn như nếu người dùng đang chạy nó sở hữu tệp.)
  • Nếu bạn thậm chí không muốn mức độ tương tác đó và mvluôn muốn (cố gắng) ghi đè lên các tệp có tên giống hệt nhau, hãy sử dụngmv -f .
  • Ngược lại, nếu bạn muốn bỏ qua các tệp nguồn khi đã có một tệp đích cùng tên, hãy sử dụng mv -n.
  • mvchấp nhận -b--backupcờ để tự động đổi tên các tệp có tên giống hệt đã tồn tại ở đích. Theo mặc định ~được thêm vào để tạo tên sao lưu và nếu một tệp có tên và một tệp có tên sao lưu đã tồn tại ở đích, thì tệp sao lưu sẽ bị ghi đè. Mặc định này có thể được ghi đè bởi các tùy chọn được truyền khi gọi mvvà bởi các biến môi trường. Xem man mvđể biết chi tiết, và ví dụ dưới đây.

Di chuyển các tệp và tạo bản sao lưu trong trường hợp tên trùng lặp:

Để di chuyển tất cả các tệp, sao lưu các tệp có tên trùng lặp bằng ~hậu tố và sử dụng hậu tố được đánh số khi các tệp đã tồn tại (để tránh ghi đè lên bất cứ thứ gì), hãy chạy:.~n~.~

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv --backup=existing {} destdir/ \;

Nếu bạn bỏ qua các tệp có tên trùng lặp và muốn biết những tệp nào:

Nếu bạn sử dụng mv -nvà muốn biết tập tin nào không được di chuyển bởi vì có một tập tin khác có cùng tên, cách tốt nhất có lẽ là chạy findlại lệnh gốc , không có -execvà mọi thứ ở bên phải của nó. Điều này sẽ in tên của họ.
Nó cũng sẽ in tên của bất kỳ tệp phù hợp nào được tạo kể từ khi bạn chạy find .... -exec ...lệnh gốc , nhưng đối với ứng dụng này thường sẽ không có ai vì bạn đang tìm kiếm các tệp có thời gian sửa đổi cũ. Bạn có thể cung cấp cho tệp một dấu thời gian sửa đổi cũ hơn so với tuổi thật của nó touchvà với các cơ chế khác, nhưng điều đó dường như không xảy ra trong trường hợp này mà bạn không biết.

Biết ngay lập tức khi các tệp bị bỏ qua do tên trùng lặp:

mv -nkhông báo cáo, cũng không trả lại bất kỳ mã thoát đặc biệt nào , khi nó không di chuyển tệp. Vì vậy, nếu bạn muốn được thông báo ngay lập tức về các tệp bị bỏ qua trong khi findchạy, bạn sẽ phải thực hiện một bước riêng cho việc đó. Một cách là:

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -n {} destdir/ \; \
    -exec [ -f {} ] \; -exec printf "\`%s' skipped (exists in \`%s')\\n" {} destdir \; 

Một vài cân nhắc kỹ thuật nhỏ có thể xảy ra: Điều này cảnh báo không chính xác nếu mvkhông sao chép tệp vì một lý do khác với lý do tồn tại ở đích và thoát báo cáo thành công . Điều đó dường như là không thể, nhưng tôi không chắc là không thể. Nó cũng có khả năng gặp phải tình trạng chủng tộc : nó sẽ cảnh báo khi không có lỗi thực sự, nếu một tệp mới cùng tên được tạo ở cùng một vị trí trong thời gian rất ngắn sau khi tệp cũ được di chuyển và trước khi kiểm tra xem nếu nó đã được gỡ bỏ. (Xem xét ứng dụng, tôi nghi ngờ một trong hai vấn đề sẽ thực sự xảy ra.) Nó có thể được viết lại để kiểm tra đích trước đódi chuyển tệp thay vì sau: điều kiện cuộc đua sẽ liên quan đến các tệp đích mới được tạo thay vì các tệp nguồn. Và trong khi các lỗi và cảnh báo được báo cáo bởi findhoặc mv(hoặc [, mặc dù không nên có) sẽ được ghi thành lỗi tiêu chuẩn , ...skipped (exists in...cảnh báo của chúng tôi được ghi vào đầu ra tiêu chuẩn . Thông thường cả hai xuất hiện trên thiết bị đầu cuối của bạn, nhưng điều này có thể quan trọng nếu bạn đang viết kịch bản.

Tôi đã chia lệnh đó thành hai dòng để dễ đọc hơn. Nó có thể được chạy theo cách đó hoặc bạn có thể loại bỏ dòng \và dòng mới (nghĩa là ngắt dòng).

findLệnh đó hoạt động như thế nào?

findcác biến vị ngữ có thể là các phép thử (như -type-newermt), được sử dụng cho các giá trị trả về hoặc các hành động (như -print-exec), thường được sử dụng cho các tác dụng phụ của chúng.

Khi không có toán tử (như -afor , -ofor hoặc ) được cung cấp giữa các biểu thức, -ađược ngụ ý. findsử dụng đánh giá ngắn mạch cho hay . (tức là ) chỉ đúng nếu các biểu thức pq đều đúng, vì vậy q không cần phải được đánh giá nếu p sai. Mặc dù chúng ta thường không nghĩ về nó trong các điều khoản này, đây là lý do tại sao các bài kiểm tra phải đúng với các hành động hoặc bài kiểm tra tiếp theo được đánh giá. Ví dụ, giả sử đến một thư mục. Nó đánh giá là sai, vì vậy nó có thể bỏ qua mọi thứ sau đó.p qp -a qfind-type f

Giống như các bài kiểm tra, hành động đánh giá là đúng hay sai. Theo cách này, -execbáo cáo nếu lệnh được thực thi thoát khỏi báo cáo thành công (đúng) hoặc thất bại (sai). Chúng tôi có chuỗi -execbiểu thức này được kết nối với ẩn :

-exec mv -n {} destdir/ \; -exec [ -f {} ] \; -exec printf "\`%s' skipped (exists in \`%s')\\n" {} destdir \;

Điều này cố gắng di chuyển tệp và nếu mvbáo cáo thất bại, dừng lại. Chúng tôi không muốn cảnh báo về một tệp bị bỏ qua chính xác nếu một số vấn đề khác là tại sao nó không được di chuyển.

Nhưng nếu nó đã thành công, nó sau đó chạy các [lệnh . Giống như find, [hỗ trợ loại biểu thức riêng của nó được truyền dưới dạng đối số. [ -f {} ]kiểm tra xem toán hạng sau -f(được truyền cho nó findthay thế {}) tồn tại (và là một tệp thông thường) và trả về giá trị true / thành công hoặc false / fail.
(Trạng thái thoát của nhiều lệnh được diễn giải tốt nhất là biểu thị thành công hay thất bại, nhưng [trạng thái tồn tại thường được hiểu là tốt nhất là đúng hoặc sai.)

Nếu [trả về sai, thì tập tin sẽ biến mất, vì vậy nó đã được di chuyển, do đó không cần phải làm gì cả. Nhưng nếu [trả về sai, tập tin vẫn còn đó. Sau đó findđánh giá -execbiểu thức tiếp theo , trong đó in thông điệp cảnh báo.

Đọc thêm


Khi tôi nhận được lúc đó, tôi hy vọng sẽ thêm một phần về xem xét hiệu suất và -exec ... +với mv -t, sometime sớm.
Eliah Kagan
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.