如何根据年份移动文件


15

我需要根据一年移动文件。我用的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...会更快。
Hauke Laging 2013年

我希望这些与coreutils有关的问题(和答案)能够按惯例指定我们是在处理GNU还是BSD(或其他)utils。
迷宫2014年

Answers:


39

您想将-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

那一定是RHEL随附的find的旧版本吗?我将在答案中提供另一种选择
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 2013年

@MichaelKjörling find可以打印所有可以打印的内容ls。可以,但有一个例外:转义/引用不愉快的字符。但是通常,的输出find可以直接排序。ls的无用调用不会使整个过程变得更快。
Hauke Laging

我经常在测试时使用非常相似的东西(尽管我个人更喜欢-print可能 -ls)。使用的优点-exec ls {}是它已经执行了外部查找。因此,当您从切换ls到时mv,实际更改很小。
CVn 2013年

3

根据手册页,-mtime的参数是您要查找的天数。您可以date +%j用来查找自当年1月1日以来的天数。


2
好方法 要非常“挑剔”:-mtime -1:是最近24小时内的任何文件。不只是昨天(或今天)的文件。因此,还会有一点“重叠”:如果您确定自2012年以来已经有120天了,今天启动脚本时是15:45,您最终将选择截至12月31日15:45的文件(而不是当天的最后一天)...您可能可以使用:nb_day-1,然后“淘汰”一些可追溯到2013年的人(可以通过ls -l | grep -v找到这些,但是如果它们只有1天大,则输出会有所不同...很多陷阱...)
Olivier Dulac

如果要使用,确实要使用该-daystart选项-mtime。否则,无论您采用何种方式旋转,都将在今年初和年末遇到文件问题,除非您恰好在午夜运行此文件。你可以做的偏移量更准确地-mmin-mtime如果你能找到,因为在新的一年里轻松的分钟数。但是,与相同的问题也存在-mtime,只是文件较少(新年夜午后一分钟左右)。
Anthon

1
是的,重新阅读该手册页后,我看到它如何将其分解为几个小时,因此做一个简单的操作find -mtime $("date -+%j")可能无法满足OP的需求。我将其留给后代使用,因为这似乎是人们可能陷入的盲点。
Bratchley

2

您可以尝试将statand和/或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
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.