Як знайти файли між двома датами за допомогою “find”?


21

У мене є обліковий запис електронної пошти, який передав 60 Гб електронних листів, і в даний час у мене виникають багато проблем з використанням клієнта електронної пошти для архівації листів минулого року (2011).

Через термінал я намагаюся використовувати пошук, щоб знайти файли між 2011-01-01 та 2011-12-31, але безрезультатно.

Як знайти файли між двома датами?

Якщо доречно, кінцевою метою буде партія, яка перемістить кожен знайдений файл, що відповідає інтервалу дати, у папку.


@EliahKagan У той час, якщо пам'ять слугує, дублювані імена не були проблемою. Тим не менш, якщо ви годуєте, що у вас є час, додаткова інформація з будь-якої заданої теми завжди цінується :) Крім того, я озвучив вашу відповідь, оскільки це дає додаткову інформацію про цю тему.
Зуул

@EliahKagan У такому випадку я закликаю вас надати відповідь з практичної безпеки, яку ви вказали :)
Зуул

Відповіді:


16

Ви можете використовувати цей сценарій:

#!/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
Вихідні дані findне повинні оброблятися в forциклі оболонки, як це, за винятком випадків, коли гарантується, що жоден файл не має порожніх пробілів у своєму імені. -exec, -execdirабо -print0 | xargsзазвичай замість цього використовувати; Іншим можливим рішенням, яке зазвичай є менш бажаним, але дозволяє використовувати forцикл, - тимчасово встановити, IFSщоб пробіл не був розпізнаний як роздільник поля.
Елія Каган

@EliahKagan так , що б команда виглядати потім: Просто замініть findз exec? Ви не хочете додати відповідь, яка стосується використання пробілів .. ?? Цінується.
SherylHohman

3
@SherylHohman Ні, не використовуйте execкоманду. Використовуйте findкоманду з -execдією, щоб виконати mv, або все, що вам потрібно виконати, як описано у відповіді, яку я зробив . Коли find... -execзапускає вашу команду із знайденими іменами шляхів, вона не використовує оболонку, тому пробіли не запускають розбиття слів або глобулювання . (Ви можете поставити нове запитання щодо вашої конкретної справи або задати саме те, що ви хочете знати.)
Eliah Kagan

@EliahKagan Вибачте, я неправильно прочитав вашу публікацію - і це було від вас ! Ти неймовірний! Ваш пост чудовий .. і дякую за відгук, хоча це була моя власна помилка в читанні !!
SherylHohman

40

Знайдіть файли між двома датами:

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

Повертає список файлів, які мають часові позначки після 2010-10-07 та до 2014-10-08

Знайдіть файли від 15 хвилин тому до цього часу:

find . -type f -mmin -15

Повертає список файлів, які мають часові позначки після 15 хвилин тому, але раніше.

Знайдіть файли між двома часовими позначками:

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

Повертає файли з часовими позначками між 2014-10-08 10:17:00та2014-10-08 10:53:00


10

Переміщення файлів та запрошення користувача, коли є повторювані імена:

Як показують відповіді Subv3rsion та Еріка Лещинського , -newermtпредикат вибирає файли, змінені останнім часом, ніж дата (і необов'язковий час), вказана як її операнд. Щоб знайти файли

  • в будь-якому місці srcdir(тобто, включаючи його підкаталоги, їхні підкаталоги тощо)
  • востаннє змінено (наприклад) у вересні 2014 року
  • і перемістити їх доdestdir

... Ви можете запустити:

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

У -execвиразі find передає ім'я файлу, знайдене замість {}. ;означає, -execщо команда, яку слід запустити, та її аргументи, всі були надані (у випадку, якщо наступні вирази передаються для пошуку після цього конкретного -execаргументу предиката - див. нижче приклад цього). ;треба уникати, \;тому що це не інтерпретується спеціально оболонкою. (Без \, ;закінчиться вся findкоманда, працює так само , як символ нового рядка. Навіть якщо ця findкоманда не має нічого після цього -execвиразу, не зумівши передати ;аргумент по - , як і раніше є синтаксичної помилкою.)

Якщо ви просто хочете перерахувати файли, що доцільно, якщо ви не впевнені, як зберігаються старі повідомлення електронної пошти або які ще файли можуть бути присутніми - опустіть -execі все праворуч від цього. (Для електронної пошти часто електронні листи з різними датами зберігаються в одному файлі; для когось із ситуацій, описаних у цьому питанні, я рекомендую вивчити, як вони зберігаються перед переміщенням будь-яких файлів.) Якщо ви хочете як надрукувати їх імена, так і перемістити їх, додайте -printраніше -exec.

mv -i підкаже будь-коли файл буде перезаписаний у пункт призначення, наприклад, якщо:

  • файл з тим самим іменем існує з попередньої резервної копії, або
  • файл з тим самим іменем, але з іншого підкаталогу srcdir, вже переміщений під час тієї ж findоперації, або
  • (найменш вірогідно) файл з тим самим іменем був створений десь srcdirпід час тієї ж findоперації, після переміщення оригіналу, але досить скоро, щоб його можна було знайти, коли він findпроходить в іншому підкаталозі.

Інші способи виклику rm:

У вас є інші варіанти, як обробляти файли з повторюваними іменами.

  • Без -i(тобто ), як правило, не вимагає затвердження, але це зробить, якби файл призначення був лише для читання. ( може навіть вдатися іноді замінити файл лише для читання, наприклад, якщо користувачеві, яким він працює, належить файл.)mv {} destdir/mvmv
  • Якщо ви не хочете навіть такої міри інтерактивності і хочете mvзавжди (намагатися) перезаписати файли з однаковою назвою, використовуйте mv -f.
  • Якщо, навпаки, ви хочете пропустити вихідні файли, коли вже є однойменний файл призначення, використовуйте mv -n.
  • mvприймає -bі --backupпрапори для автоматичного перейменування ідентично названих файлів, які вже є в пункті призначення. За замовчуванням ~додається ім'я резервної копії, і якщо файл з ім'ям та файл із ім’ям резервної копії вже є в пункті призначення, файл резервної копії буде перезаписаний. Цей параметр за замовчуванням може бути замінений параметрами, що передаються при виклику mv, та змінними середовища. Див man mvподробиці і приклад нижче.

Переміщення файлів та створення резервних копій у разі дублювання імен:

Щоб перемістити всі файли, створити резервну копію файлів із дублюючими іменами за допомогою ~суфікса та використовувати нумеровані суфікси, коли файли вже існують (щоб уникнути нічого перезапису), запустіть:.~n~.~

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

Якщо ви пропустили файли з повторюваними іменами і хочете знати, які з них:

Якщо ви користуєтесь mv -nі хочете дізнатися, які файли не переміщені, тому що був ще один файл з такою ж назвою, найкращий спосіб - це, мабуть, просто запустити початкову findкоманду ще раз, без -execі все праворуч від неї. Це надрукує їх імена.
Він також надрукує імена будь-яких відповідних файлів, створених з моменту запуску оригінальної find .... -exec ...команди, але для цієї програми зазвичай не буде жодної, оскільки ви шукаєте файли зі старими часовими модифікаціями. Можна надати файлу часову позначку модифікації, старшу за його реальний вік, за допомогою touchта інших механізмів, але це, мабуть, не трапиться в цьому випадку без вашого відома.

Негайно знаючи, як файли пропускаються через дублюючі імена:

mv -nне повідомляє і не повертає спеціального коду виходу , коли він утримується від переміщення файлу. Отже, якщо ви хочете бути негайно поінформовані про пропущені файли під час findзапуску, вам доведеться зробити для цього окремий крок. Один із способів:

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 \; 

Кілька, ймовірно, незначних технічних міркувань: Це попереджає неправильно, якщо mvне вдасться скопіювати файл з іншої причини, ніж існуючий у пункті призначення, і закінчується повідомлення про успіх . Це здається малоймовірним, але я не впевнений, що це неможливо. Він також потенційно страждає від умови перегонів : він би попереджав, коли немає справжньої помилки, якби новий файл з таким самим іменем був створений на тому самому місці протягом дуже короткого часу після переміщення старого файлу та перед перевіркою на подивіться, чи його зняли. (Що стосується програми, я сумніваюся, що будь-яка проблема коли-небудь насправді виникне.) Це можна було б переписати, щоб перевірити місце призначення ранішепереміщення файлу замість після: тоді умова перегонів буде стосуватися новостворених файлів призначення замість вихідних файлів. І хоча помилки та попередження, про які повідомляє findабо mv(або [, хоча їх не повинно бути), будуть записуватися до стандартної помилки , наше ...skipped (exists in...попередження надходить до стандартного виводу . Зазвичай обидва з'являються у вашому терміналі, але це може мати значення, якщо ви пишете сценарії.

Я розділив цю команду на два рядки для легшого читання. Її можна запустити таким чином, або ви можете видалити \і новий рядок (тобто, розрив рядка).

Як працює ця findкоманда?

findпредикати можуть бути тестами (як -typeі -newermt), що використовуються для їх повернення значень, або дії (як -printі -exec), які часто використовуються для їх побічних ефектів.

Коли жоден оператор (як -aдля і , -oдля чи ) не надається між виразами, -aмається на увазі. findвикористовує оцінку короткого замикання для та та або . (тобто ) є істинним лише в тому випадку, якщо вирази p і q є істинними, тому q не потрібно оцінювати, якщо p є хибним. Хоча ми часто не думаємо про це в цих термінах, саме тому тести повинні бути правдивими для наступних дій або тестів, які повинні бути оцінені. Наприклад, припустимо, виникає каталог. Він оцінюється як хибний, тому він може пропустити все згодом.p qp -a qfind-type f

Як і тести, дії також оцінюються як істинні чи помилкові. Таким чином, -execзвітує, якщо виконана команда завершила успіх у звіті (вірно) або провал (помилка). У нас цей ланцюжок -execвиразів пов'язаний із неявними та :

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

Це намагається перемістити файл, і якщо mvповідомлення про помилку, зупиняється. Ми не хочемо попереджати про правильно пропущений файл, якщо якась інша проблема була причиною його не переміщення.

Але якщо це вдалося, то вона працює на [команду . Мовляв find, [підтримує свій вид виразів, переданих як аргументи. [ -f {} ]перевіряє, чи існує операнд після -f(переданий йому findзамість {}) і є звичайним файлом, і повертає або істинний / успішний, або хибний / невдалий.
(Статуси виходу багатьох команд найкраще трактувати як ознаку успіху чи невдачі, але [існуючий статус, як правило, найкраще тлумачити як істинний або хибний.)

Якщо [повернуто помилкове значення, файл не зникне, тому його перемістили, тому нічого робити не потрібно. Але якщо [повернуто помилкове, файл все ще є. Потім findоцінюється наступний -execвираз, який друкує попереджувальне повідомлення.

Подальше читання


Коли я знайду час, я сподіваюсь додати розділ про міркування щодо ефективності, а -exec ... +також mv -tнезабаром.
Елія Каган
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.