如何使用“查找”在两个日期之间查找文件?


21

我的电子邮件帐户已通过60GB的电子邮件,目前在使用电子邮件客户端存档去年(2011年)的电子邮件时遇到很多麻烦。

通过终端,我尝试使用find来查找2011-01-01和2011-12-31之间的文件,但无济于事。

如何找到两个日期之间的文件?

如果相关的话,最终目标将是一批将与日期间隔匹配的找到的每个文件移动到一个文件夹的批处理。


@EliahKagan当时,如果有记忆的话,重复的名称就不成问题了。尽管如此,如果您有空的话,总是会感谢您提供有关任何给定主题的更多信息:)此外,我还对您的答案进行了投票,因为它提供了关于该主题的更多见解。
Zuul 2014年

@EliahKagan在这种情况下,我鼓励您提供您所强调的实用故障保险的答案:)
Zuul 2014年

Answers:


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不应在这样的shell for循环中处理的输出。-exec-execdir-print0 | xargs通常应改为使用;另一种可能的解决方案for是临时设置,通常不那么理想,但确实允许使用循环,IFS因此不能将空格识别为字段分隔符。
伊利亚·卡根

@EliahKagan那么命令将是什么样子:只需替换findexec?您介意添加一个解决空格使用问题的答案吗?非常感激。
SherylHohman '17

3
@SherylHohman不,不要使用exec命令。使用find命令执行-exec操作mv,或者执行任何操作,如我发布的答案所述。当find... -exec使用找到的路径名运行命令时,它不使用外壳程序,因此空格不会触发单词拆分globlob。(您可能想对特定情况发布一个新问题,或者确切地问您想知道什么。)
Eliah Kagan

@EliahKagan对不起,我看错了您的帖子,那是您发来的!你真棒!您的帖子很棒..并且感谢您的回复,即使这是我自己在阅读中的错误!
SherylHohman

40

Bash查找两个日期之间的文件:

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

返回具有时间戳的文件列表,此文件的时间戳记在2010-10-07之后,在2014-10-08之间

Bash从15分钟前到现在查找文件:

find . -type f -mmin -15

返回在15分钟之前但现在之前具有时间戳的文件列表。

Bash查找两个时间戳之间的文件:

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

移动文件,并在名称重复时提示用户:

Subv3rsionEric Leschinski的答案所示,-newermt谓词选择的文件的修改时间比指定为其操作数的日期(和可选时间)更新的时间最近。查找文件

  • 任何地方srcdir(即,包括其子目录,子目录等)
  • 最后修改时间(例如):2014年9月
  • 并将它们移到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由于与目的地不同的原因而无法复制文件,则会错误地发出警告,并退出报告成功。这似乎不太可能,但我不确定这是不可能的。它还可能会出现竞争状况:如果在移走旧文件之后以及在检查到看看是否已将其删除。(考虑到该应用程序,我怀疑这两个问题是否会真正发生。)在执行之前,可以将其重写以检查目标位置移动文件而不是移动文件:竞争条件将与新创建的目标文件而不是源文件有关。而且,虽然findmv(或[,尽管不应出现)报告的错误和警告将写入标准错误,但我们的...skipped (exists in...警告会写入标准输出。通常,两者都出现在您的终端上,但是如果您编写脚本,这可能很重要。

我将该命令分为两行,以方便阅读。可以通过这种方式运行,也可以删除\和换行符(即换行符)。

find命令如何工作?

find谓词可以是用于返回值的测试(如-type-newermt),或通常用于其副作用的动作(如-print-exec)。

如果在表达式之间未提供任何运算符(例如-afor for ,-ofor ),则表示-a为隐含的。find采用短路评价。(即)仅当pq表达式均为true时才为true,因此如果p为false 则不需要对q进行求值。尽管我们通常不以这些术语来考虑它,但是这就是为什么对于随后的动作或要评估的测试,测试必须为真。例如,假设出现在目录中。它的计算结果为false,因此以后可以跳过所有内容。p qp -a qfind-type f

与测试一样,动作的评估结果也为真或假。以这种方式,-exec报告执行的命令是否退出,报告成功(true)或失败(false)。我们使这一系列-exec表达式与隐式相连:

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

这将尝试移动文件,如果mv报告失败,则停止。如果由于其他原因导致文件未移动,我们不想警告正确跳过的文件。

但是,如果它成功了,它然后运行[命令。Like find[支持作为参数传递的其自身类型的表达式。[ -f {} ]检查之后的操作数-ffind代替传递给它{})是否存在(并且是常规文件),并返回true / success或false / failure。
(最好将许多命令的退出状态解释为表示成功或失败,但是[通常将其存在状态最好解释为对或错。)

如果[返回false,则文件不见了,因此被移动了,因此无需执行任何操作。但是,如果[返回false,则该文件仍然存在。然后find计算下一个-exec表达式,该表达式将打印警告消息。

进一步阅读


我希望在有空的时候尽快添加有关性能注意事项的部分,并-exec ... +使用mv -t
伊莱亚·卡根
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.