如何列出在一定时间内更改的文件?


38

如何递归列出在2011年12月22日到2011年12月24日之间更改的所有文件?


6
如果您的意思是“最后一次更改”,那么您就有机会解决。如果文件在2011年12月26日被修改,则无法确定在给定范围内是否也对其进行了修改。(除非您有一个非常特殊的文件系统。)
William Pursell 2012年

Answers:


25

一般来说,当您在目录及其子目录中递归查找文件时,请使用find

指定日期范围的最简单方法find是在该范围的边界创建文件并使用-newer谓词。

touch -t 201112220000 start
touch -t 201112240000 stop
find . -newer start \! -newer stop

为什么在-newer这里需要否定第一个的输出?
亚历山大·斯卡

@AlexanderCska第一个-newer是否定的,第二个是否定的。“查找比更新start但不更新的文件stop”。
吉尔斯(Gillles)“所以-别再作恶了”

确定否定之后对命令起作用。如果不存在否定,将会发生什么?
亚历山大·卡斯卡

@AlexanderCska然后,您将获得比start和都更新的文件stop
吉尔斯(Gillles)“所以-别再邪恶了”

35

使用Gilles的解决方案,并再次阅读man find(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上运行良好。


很酷的技巧,谢谢!这帮助我找到含有与成千上万的文件目录的某个关键字最近的文件:find -newermt 20150212 \! -newermt 20150213 | xargs grep 'keyword' -m 50 -l-m 50=在第50行搜索)。
罗布W

@RobW:实际上,您可以使用-exec ... +in 来保留管道和xargs find(1),例如:find -newermt 20150212 \! -newermt 20150213 -exec grep keyword -m 50 -l {} +。这样做是一样的,但是更便宜。
TrueY

我必须用双引号将时间戳记起来(我在Ubuntu Xenial上使用find 4.7.0-git)。
IsaacS

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))

编辑:更改cminmmin@Eelvex的评论后。 编辑: “ \!” 失踪


嗯似乎不起作用。您确定它递归地遍历子目录吗?

是的,它对我有效。您确实在那个时间范围内修改过文件吗?在不同的时间范围内尝试。
onurgüngör2012年

6
-cmin是“状态更改”,-mmin是“数据更改”。您可能想要-mmin
Eelvex 2012年

3

find可以采用ISO格式的日期时间,因此,例如对于UTC上的服务器,您可以指定从任何位置开始的小时数偏移量。由于还要比较时间,因此这也需要增加一天的时间:

find -type f -newermt 20111224T0800 \! -newermt 20111225T0800

0

请注意,标记为重复的问题因此被限制直接回答,这就是为什么我要在此处发布。该答案用于回答问题“需要根据创建日期将文件移动到其他文件夹[重复]”

答案是合理的,但是纯find命令存在一些局限性。我编写了这个Shell脚本,以浏览其中包含许多文件的目录,文件系统正盯着元数据试图执行ls。另外,某些* nix系统会在运行ls时阻止过多的参数错误。

find命令非常强大,我从列出的方法开始,但是在该目录中有很多年的数据,不得不反复遍历所有文件。这会在每个文件上产生大量不必要的传递。我尝试每年做一个屏幕并运行多个查找,但这会导致每个查找产生很多错误,并且其中一个查找移动它时文件会丢失。

我的Shell脚本将文件移动到具有4位数字的年份和2位数字的月份的目标目录。通过取消注释几行并注释掉对应的行,可以轻松地将其扩展为两位数。我相信它会更高效,因为它是通过一次遍历find来执行移动的,因此不需要多个find命令和目录上的传递。

#!/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 /path/to/directory -type f -exec /home/username/move_files.sh {} \;

您不必担心将newermt选项设置为find,因为所有find提供的是对找到的每个文件执行一次,脚本会做出所有决定。

请记住,如果不选择-type f,它将移动目录,这可能会导致问题。如果您只想移动目录,也可以使用-type d。不设置类型几乎可以肯定会产生不必要的行为。

请记住,该脚本符合我的需求。您可能只想使用我的构造作为灵感,以更好地满足您的需求脚本。谢谢!

注意事项:通过允许无限数量的参数通过脚本,可以极大地提高命令的效率。如果传递$ @变量,这实际上相对容易。扩展此功能将使我们能够使用find的-exec +函数或利用xargs。我可能会很快实现并改善自己的答案,但这只是一个开始。

由于这是一次脚本会议,因此可能需要进行许多改进。祝好运!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.