Как переместить файлы на основе года


14

Мне нужно переместить файлы на основе года. Я использовал findкоманду

find /media/WD/backup/osool/olddata/ -mtime +470 -exec ls -lrth {} \;|sort -k6

но для успешного выполнения этой команды мне нужно знать точное значение mtime470, это всего лишь предположение. Означает, что если я могу дать 2012 год, он дает мне файлы, относящиеся только к 2012 году.

Поэтому мне нужен совет о том, как

Найдите файлы по году, например, 2012 и переместите их в другой каталог.

OS release 5.2

FIND version
GNU find version 4.2.27
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX 

Имеет ли смысл использовать -exec ls ... \;вместо -exec ... +? Ваша находка слишком старая для этого? В этом случае find ... -print0 | xargs -0 ls...будет намного быстрее.
Хауке Лагинг

Я хотел бы, чтобы эти вопросы (и ответы), которые касаются coreutils, обычно указывали, имеем ли мы дело с GNU или BSD (или другими) утилитами.
Лабиринт

Ответы:


37

Вы хотите использовать -newermtопцию для find:

find /media/WD/backup/osool/olddata/ -newermt 20120101 -not -newermt 20130101

получить все файлы со временем модификации в 2012 году.

Если ваша находка не поддерживает, -newermtвы также можете сделать следующее, чтобы предотвратить использование вычислений смещения:

touch -d 20120101 /var/tmp/2012.ref
touch -d 20130101 /var/tmp/2013.ref
find /media/WD/backup/osool/olddata/ -newer /var/tmp/2012.ref -not -newer /var/tmp/2013.ref

1
-newermt флаг недоступен в команде поиска
OmiPenguin

Это должно быть старая версия find, с которой идет ваш RHEL? Я предоставлю альтернативу в ответе за это
Anthon

Да, это 5,2
OmiPenguin

Я так понимаю, что это ревизия RHEL, а не find(у меня есть версия 4.4.2)
Anthon

1
Переключатель newermt не показывал в находке до версии после v4.3.3, gnu.org/software/findutils/manual/html_mono/find.html .
SLM

5
touch --date=2011-12-31T23:59:59 start
touch --date=2012-12-31T23:59:59 stop
find / -newer start \! -newer stop -printf %Tx" "%p\\n

-exec ls не имеет никакого смысла.


1
-exec ls -lимеет больше смысла, и даже больше во время тестирования.
CVn

@ MichaelKjörling findможет напечатать все, что lsможет. Хорошо, с одним исключением: экранирование / цитирование неприятных символов. Но в целом вывод findможет быть отсортирован напрямую. Бесполезные вызовы ls не делают все это быстрее.
Хауке Лагинг

Я очень часто использую что-то очень похожее (хотя лично я предпочитаю -printили возможно -ls ) во время тестирования. Преимущество использования -exec ls {}состоит в том, что он уже выполняет что-то внешнее, чтобы найти . Так что к тому времени , когда вы переключаться с lsна mvфактические изменения минимальны.
CVn

3

Согласно справочной странице, аргумент -mtime - это количество дней, которое вы ищете. Вы можете использовать, date +%jчтобы узнать количество дней с 1 января текущего года.


2
Хороший способ. Быть очень "придирчивым": -mtime -1: любой файл за последние 24 часа. Не только файлы вчера (или сегодня). Таким образом, также будет небольшое «наложение»: если вы определите, что с 2012 года прошло 120 дней, а сегодня - 15: 45, когда вы запускаете скрипт, вы в конечном итоге выберете файлы до 31 декабря 15:45 ( и не последние в тот день) ... Вы, вероятно, можете использовать: nb_day - 1, а затем "отсеять" тех, кто датируется 2013 годом (их можно найти с помощью ls -l | grep -v, НО выходной отличается, если они только 1-дневного возраста ... много подводных камней ...)
Оливье Дюлак

Вы хотите использовать -daystartопцию, если вы собираетесь работать с -mtime. В противном случае у вас будут проблемы с файлами в начале и конце года, куда бы вы ни пошли, если вы не запустите это точно в полночь. Вы можете сделать смещение более точно, -mminчем с помощью, -mtimeесли вы можете легко найти количество минут с нового года. Но та же проблема существует с тем же, что и с -mtime, только для меньшего количества файлов (это одна минута около полуночи нового года).
Anthon

1
Да, перечитывая справочную страницу, я вижу, как она разбивается на несколько часов, поэтому простое выполнение, find -mtime $("date -+%j")вероятно, не даст ОП, чего они хотят. Я оставляю это для потомства, так как это кажется возможным слепым пятном для людей, чтобы попасть в.
Братчли

2

Вы можете попробовать использовать комбинацию с командами statи / или, dateкак в следующих однострочниках:

BSD / Mac OS X:

find . -type f -print | while read file; do eval `stat -s "$file"`; year=`date -jf "%s" "+%Y" "$st_mtime"`; dest="/path/to/destination/$year; mkdir -p "$dest"; mv "$file" "$dest"; done

Linux:

find . -type f -print | while read file; do year=`date -r "$file" "+%Y"`; dest="/path/to/destination/$year; mkdir -p "$dest"; mv "$file" "$dest"; done

В обоих случаях подход заключается в использовании dateкоманды для извлечения года из времени последнего изменения каждого файла, а затем для создания пути с этим годом. Команда mkdir -pсоздаст этот путь, если он еще не существует. Конечно, вы можете использовать некоторые другие findпараметры для уточнения поиска.


1

Если вы делаете это из рабочего каталога, вы можете сделать это вместо этого:

ls -l |awk '{ if ($8 == "2013") print $9 }'

Это значительно упрощает вещи и не вызывает совпадений. Но это также предполагает, что эти файлы старше 6 месяцев, и в них lsбудет напечатан год, а не точное время.

Для файлов старше 6 месяцев вам просто нужно заменить их на это:

ls -l |awk '{ if ($6 == "May") print $9 }' 

или что-то подобное, в зависимости от месяца. Если вы хотите создать список месяцев для перемещения файлов (или если вы хотите создать список на годы), сделайте следующее:

month="May Jun Jul"; 
for i in `echo $month`; 
do 
    for j in `ls -l |awk '{ if ($6 == "'$i'") print $9}'`
    do
        mkdir -p $i
        mv $j $i
    done
done
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.