Переміщення файлів та запрошення користувача, коли є повторювані імена:
Як показують відповіді 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вираз, який друкує попереджувальне повідомлення.
Подальше читання