Как вывести список файлов, которые были изменены за определенный промежуток времени?

38

Как я могу рекурсивно перечислить все файлы, которые были изменены с 22.12.2011 по 24.12.2011?

зажим
источник
6
Если вы имеете в виду «последнее изменение», у вас есть шанс найти решение. Если файл был изменен 26.12.2011, вы не можете сказать, был ли он также изменен в заданном диапазоне. (Если у вас нет очень экзотической файловой системы.)
Уильям Перселл

Ответы:

25

Вообще говоря, когда вы ищете файлы в каталоге и его подкаталогах рекурсивно, используйте find.

Самый простой способ указать диапазон дат find- создать файлы на границах диапазона и использовать -newerпредикат.

touch -t 201112220000 start
touch -t 201112240000 stop
find . -newer start \! -newer stop
Жиль "ТАК - прекрати быть злым"
источник
почему отрицание вывода первого -newerнеобходимо здесь?
Александр Цска
@AlexanderCska Первый -newerне отрицается, второй. «Найти файлы, которые новее, чем, startно не новее, чем stop».
Жиль "ТАК - перестань быть злым"
ОК отрицание работает по команде после. Что бы произошло, если бы не было отрицания?
Александр Цска
@AlexanderCska Тогда вы получите файлы, которые новее, чем оба startи stop.
Жиль "ТАК - перестань быть злым"
35

Используя решение Жиля, и после прочтения мужчина снова нашел (1), я нашел более простое решение. Лучшим вариантом является -newerXY. Можно использовать флаги m и t.

m   The modification time of the file reference
t   reference is interpreted directly as a time

Так что решение

find . -type f -newermt 20111222 \! -newermt 20111225

Нижняя граница включительно, а верхняя граница исключительна, поэтому я добавил к ней 1 день! И это рекурсивно. Хорошо работает на find v4.5.9.

TrueY
источник
Прикольный трюк, спасибо! Это помогло мне найти недавний файл, содержащий определенное ключевое слово в каталоге с тысячами файлов: find -newermt 20150212 \! -newermt 20150213 | xargs grep 'keyword' -m 50 -l( -m 50= поиск в первых 50 строках).
Роб W
@RobW: На самом деле вы можете сэкономить трубу и xargs , используя -exec ... +в find(1), как: find -newermt 20150212 \! -newermt 20150213 -exec grep keyword -m 50 -l {} +. Это делает то же самое, но дешевле.
Правда,
Мне пришлось заключить временные метки в двойные кавычки (я в Ubuntu Xenial с find 4.7.0-git).
Исаак
13

В дополнение к уже даным ответам, обратите внимание, что вы можете напрямую указать свои даты:

find -type f -newermt "2011-12-22" \! -newermt "2011-12-24"

или

find -type f -newermt "2011-12-22 00:00:00" \! -newermt "2011-12-24 13:23:00"

если вы дополнительно хотите указать время.

ученик
источник
6

Предполагая, что вам не нужна точность до секунд, это должно сработать.

find . -type f -mmin -$(((`date +%s`-`date -d 20111222 +"%s"`)/60)) \! -mmin +$(((`date +%s`-`date -d 20111224 +"%s"`)/60))

EDIT: Изменены cminк mminпосле @ комментарий Eelvex в. РЕДАКТИРОВАТЬ: '\!' отсутствует

онур гюнгёр
источник
хм не похоже на работу. Вы уверены, что он рекурсивно идет по подкаталогам?
зажим
Да, это работает на меня. Вы действительно изменили файлы за этот промежуток времени? Попробуйте это с разными временными диапазонами.
Онур Гюнгёр
6
-cminэто «изменение статуса», -mminэто «изменение данных». Вы, вероятно, хотите-mmin
Eelvex
3

findМожно использовать формат даты и времени в формате ISO, поэтому для сервера, например, в формате UTC, вы можете указать смещение количества часов, где бы вы ни находились. Это также позаботится о том, чтобы добавить день, так как вы тоже сравниваете время:

find -type f -newermt 20111224T0800 \! -newermt 20111225T0800
Алекс Янг
источник
0

Пожалуйста, обратите внимание, что вопрос, помеченный как дубликат, и поэтому ограничен от прямого ответа, поэтому я публикую здесь. Этот ответ предназначен для ответа на вопрос «необходимо переместить файлы в другую папку на основе даты создания [дубликата]»

Ответы разумны, но с чисто командой поиска были некоторые ограничения. Я написал этот сценарий оболочки, чтобы пройти через каталог с таким количеством файлов, что файловая система давала метаданные, пытаясь выполнить ls. Кроме того, некоторые системы * nix будут выдавать ошибку слишком многих аргументов при запуске ls.

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

Мой сценарий оболочки перемещает файл в каталог назначения с 4-значным годом и 2-значным месяцем. Его можно легко расширить до двухзначного дня, раскомментировав пару строк и закомментировав их аналоги. Я считаю, что он более эффективен, потому что он выполнял шаги за один проход поиска, поэтому несколько команд поиска и проходов по каталогу не нужны.

#!/bin/bash
#We want to exit if there is no argument submitted
if [ -z "$1" ]
then
  echo no input file
  exit
fi

#destDir should be set to where ever you want the files to go
destDir="/home/user/destination"

#Get the month and year of modification time
#--format %y returns the modification date in the format:
# 2016-04-26 12:40:48.000000000 -0400
#We then take the first column, split by a white space with awk
date=`stat "$1" --format %y | awk '{ print $1 }'`

#This sets the year variable to the first column split on a - with awk
year=`echo $date | awk -F\- '{print $1 }'`
#This sets the month variable to the second column split on a - with awk
month=`echo $date | awk -F\- '{print $2 }'`
#This sets the day variable to the third column split on a - with awk
#This is commented out because I didn't want to add day to mine
#day=`echo $date | awk -F\- '{print $3 }'`

#Here we check if the destination directory with year and month exist
#If not then we want to create it with -p so the parent is created if
# it doesn't already exist
if [ ! -d $destDir/$year/$month ]
then
  mkdir -p $destDir/$year/$month || exit
fi

#This is the same as above but utilizes the day subdirectory
#Uncommented this out and comment out the similar code above
#if [ ! -d $destDir/$year/$month/$day ]
#then
#  mkdir -p $destDir/$year/$month$day || exit
#fi

#Echoing out what we're doing
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
echo Moving $1 to $destDir/$year/$month
#echo Moving $1 to $destDir/$year/$month/$day

#Move the file to the newly created directory
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
mv "$1" $destDir/$year/$month
#mv "$1" $destDir/$year/$month/$day

После сохранения и создания исполняемого файла вы можете вызвать этот скрипт с помощью команды find следующим образом.

find /path/to/directory -type f -exec /home/username/move_files.sh {} \;

Вам не нужно беспокоиться об установке параметра newermt для find, поскольку все, что находит find, - это одно выполнение для каждого найденного файла, и скрипт принимает все решения.

Имейте в виду, что если вы не выберете -type f, это приведет к перемещению каталогов, что может вызвать проблемы. Вы также можете использовать -type d, если хотите переместить только каталоги. Отсутствие установки типа почти наверняка приведет к нежелательному поведению.

Помните, что этот сценарий был адаптирован к моим потребностям. Возможно, вы захотите просто использовать мою конструкцию как источник вдохновения для лучшего сценария ваших потребностей. Спасибо!

Соображения: эффективность команды может быть БОЛЬШО повышена за счет разрешения неограниченному количеству аргументов проходить через скрипт. На самом деле это относительно просто, если вы передадите переменную $ @. Расширение функциональности этого позволило бы нам использовать, например, функцию find -exec + или использовать xargs. Я могу быстро реализовать это и улучшить свой собственный ответ, но это только начало.

Поскольку это был сеанс сценария с одним выстрелом, вероятно, можно сделать много улучшений. Удачи!

Vex Mage
источник