查找在shell中的另一个文件的五天内创建的文件

时间:2013-07-18 13:57:24

标签: shell sh qnx qnx-neutrino

我仍然很喜欢脚本,所以请坚持下去,如果您有任何疑问,请随时提出。

好的,所以: 我有一个文件让我们说 file.txt

file.txt 存在于目录/this/is/the/directory/file.txt

在单独的目录中存在.log文件,告诉我在创建 file.txt 时会发生什么。

fuubar.log,fuu.log,bar.log,this.log,that.log,some.log,other.log ......这些日志数量未知。< / p>

我需要收集正在创建的 file.txt 文件 + - 5 天的所有日志文件。

例如: file.txt 是在2013年7月7日创建的(不要注意日期格式) 我需要2013年7月2日到2013年7月12日之间发生的日志文件。

有什么想法吗?

编辑:我对比较文件的日期以获得正确的日期感到困惑,我知道如何复制文件。

我无法使用Perl和stat

3 个答案:

答案 0 :(得分:4)

除非有人发布单行内容,否则有什么可以让你开始!

# Get the date in you want to start listing files from using your
# sample file. This will assign the variable in the format of MMDDYYYY
$ start=$(date -d "-5 days" '+%m%d%Y' < <(date -r /this/is/the/directory/file.txt))

# Get the date in you want to end listing files from. using your
# sample file. This will assign the variable in the format of MMDDYYYY
$ end=$(date -d "+5 days" '+%m%d%Y' < <(date -r /this/is/the/directory/file.txt))

# Create two temp files. touch -t will force the timestamp on
# these files to match the content of variables
$ touch -t "$start" /tmp/s$$
$ touch -t "$end" /tmp/e$$

# Use these temp files timestamp as a pivot mechanism by find commands
# newer option. This will list files whose timestamp is in between our 
# temp files timestamp which we captured from your sample file
$ find /path/to/files -type f -newer /tmp/s$$ -and -not -newer /tmp/e$$

答案 1 :(得分:2)

由于您使用的是QNX,因此您不能在现有方法中使用现有的POSIX / Linux / Unix / BSD脚本。如果您可以安装可以帮助您执行此操作的编程语言或安装更新的系统实用程序(从QNX希望)或shell工具来实现相同的功能可能会更容易,但我意识到这并不总是可行的。

你可以尝试以下可怕的hackish方法来快速“立即行动”解决方案:

首先使用find /path/to/log/file.txt -printf %Cj为您提供创建日志文件的1-366中的一年,以及-printf %CY为您提供年份值。接下来使用expr +/- 5来查找$ day_of_year_start和$ day_of_year_end的值,然后您可以使用它们设置$start$end变量,就像在JP的脚本中一样我的变化。

现在您需要一种方法来获取与date -s一起使用的纪元时间,以便您可以将纪元转换为touch -t将使用的时间格式。如果没有可以转换到纪元时间的date而没有strftime输出纪元时间以使其变得容易,则需要“黑客”。一种混乱的方法是在一年开始时设置一个常量(例如2013年1月1日的1356998400;如果需要,再加上其他年份的值),然后添加($ day_of_year_start x 86400)和($ day_of_year_end x 86400) )秒到该常量,以便在QNX上通过date -s获得两个纪元时间值,并分别为$start$end设置日期/时间戳。

凌乱但实际上可能有效:-)如果您尝试这个,请告诉我们。

干杯, ps:这是脚本的开始,你需要检查QNX的命令参数和日期格式,以确保它们是正确的。它适用于我使用gfind(GNU查找)和date -r的BSD框(而不是date -s用于QNX)。

#!/bin/sh
# Find files created within 5 days before/after
# the creation of another file on QNX.
# 
#  ./rangesearch /path/to/logfile.txt
# 
# NB: 
# QNX shell environment lacks some POSIX/GNU features:
# 1. 'stat', 'date -r' are not available (use find to get file ACM dates)
# 2. use GNU 'find' extensions (since -printf is needed for output of dates)
# 3. 'date' cannot modify dates using day/month/year values so we convert
#    to epoch values in a roundabout way. 'find' cannot output epoch dates
#    due to limitations of QNX strftime so we compare year of file creation
#    against a set of constants and then add/subtract daily amounts of 
#    seconds from this value and use QNX 'date -s' to convert these dates to 
#    formats usable by QNX 'touch'. 
#
# TODO: improve and extend year <--> epoch time constant matching with
#       an array and for loop (Bourne shell 'sh' does not really have
#       an "array" feature per se). 
#
#       detect version of find/gfind date/gdate so this runs on Linux OSX BSD 
#
#       add more precise units (hours minutes seconds) to epoch time
#       calculation (exercise for reader)
#

year2013="1357016400"
year2012="1325394000"
year2011="1293858000"
year2010="1262322000"
# .... etc etc,  some kind of vector or array would be nice ...

fileyear=`find $1 -printf %CY`
filedoyr=`find $1 -printf %Cj`

if [ $fileyear -eq "2013" ]; then
  logfile_epoch=$(( $year2013 + ($filedoyr * 86400) ))
  echo "file is from $fileyear or $logfile_epoch SSL"
elif [ $fileyear -eq "2012" ]; then
  logfile_epoch=$(( $year2012 +($filedoyr * 86400) ))
  echo "file is from $fileyear or $logfile_epoch SSL"
elif [ $fileyear -eq "2011" ]; then
  logfile_epoch=$(( $year2011 + ($filedoyr *86400) ))
  echo "file is from $fileyear or $logfile_epoch SSL"
elif [ $fileyear -eq "2010" ]; then
  logfile_epoch=$(( $year2010 + ($filedoyr *86400) ))
  echo "file is from $fileyear or $logfile_epoch SSL"
else
  echo "there is a problem"
  exit
fi

echo "file is from day $filedoyr of $fileyear"

epochal_start=$(( $logfile_epoch - (5*86400) ))
epochal_end=$(( $logfile_epoch + (5*86400) ))
start=`date -s $epochal_start +%Y%m%d%H%S`
end=`date -s $epochal_end +%Y%m%d%H%S`

echo "epochal_start $epochal_start"
echo "epochal_end $epochal_end"

echo -e "Searching for files from $start to $end in age \n...\n"

touch -t "$start" /tmp/s$$
touch -t "$end" /tmp/e$$

# -print0 and xargs -0 allow for file names with whitepace
find . -type f -newer /tmp/s$$ -and ! -newer /tmp/e$$ -print0 |xargs -0 ls -tal

# clean temporary files:
rm /tmp/s$$
rm /tmp/e$$

这里的SSL意味着很久以前的秒数: - )

答案 2 :(得分:1)

通常没有simple portable (POSIX) way to get file modification times

请注意,如果您的Unix版本find包含GNU扩展(如-printf),您可以使用find来获取原始日志文件的日期。如果您的date版本未包含-v以及时向前和向后调整日期字符串,那么您必须找到一些方法将日期转换为大纪元日期(很久以前的秒数)和使用expr(+/- 86400 * 5)调整日期,并将其转换为touch可用的格式。

您已告诉我们您正在使用QNX,因此对于find的QNX版本,您将获得-printf扩展名。这意味着您可以使用find创建值,但无法使用date -v +/- 5天进行调整,或将其转换为大纪元时间,以便使用expr进行修改。 QNX文档似乎没有说明如何以一种简单明显的方式实现这一点,说明为什么simple portable (POSIX shell) way to get file modification times, set the date, convert date formats, etc. etc.在现实世界中会如此美妙。您需要向QNX大师们寻求更多帮助。抱歉!

为了补充Jaypal Singh的GNU coreutils解决方案BSD / POSIX和Perl方法。

对于BSD派生系统(FreeBSD,DragonFly,可能是OS / X),替换在@ JS解决方案中创建$start$end变量的命令,可能会有以下效果:

#!/bin/sh
#
middle=`stat -r file.txt | cut -d" " -f10` # file.txt could 
                                           # come from a script 
                                           # positional argument like $1



# the number date range could also come from a positional argument like $2

start=`date -v-5d -r $middle +%Y%m%d%H%S`
end=`date -v+5d -r $middle +%Y%m%d%H%S`

touch -t "$start" /tmp/s$$
touch -t "$end" /tmp/e$$

find . -type f -newer /tmp/s$$ -and ! -newer /tmp/e$$

@JS已经描述过的脚本的最后一部分。

另一种选择是让某人骑着跨平台的骆驼来救援......像这样: - )

这当然可以更好,但这里的perl方法来自find2perl输出:

#!/usr/bin/env perl  
# findrange  Usage: cd /dir/to/search ; findrange 5 /file/to/compare.txt

use strict;  use warnings;                                            
use File::Find ();                                                          
use vars qw/*name/;                                                         

*name   = *File::Find::name;                                                

sub wanted;                                                                 

# some values to use                                                        
my $RANGE = $ARGV[0] ;  # get date range                                    
my $REF_FILE = $ARGV[1] ;  # get file to compare date                       
my $AGE_REF = -M $REF_FILE ;                                                
my $start = $AGE_REF - $RANGE ; # +/- days from @ARGV[0] 
my $end = $AGE_REF +  $RANGE ;                                              

# Descend file system searching/finding.                                     
# from current directory  "."                                               
File::Find::find({wanted => \&wanted}, '.');                                
exit;                                                                       

sub wanted {                                                                
  ( lstat($_)) &&  #caches results in "_" for -M to use   
    -f _ &&                                                                 
    (-M _ > $start) &&                                                      
    ! (-M _ > $end)                                                         
    && print("$name\n");                                                    
}                                                                           

如果是交互式使用,您可以添加:

if ($#ARGV != 1) {  # require 2 args (last array index +1)
 usage() ;  
 }
sub wanted运行之前/之前

以及类似sub usage { print "whatever \n"; exit;}之类的内容,以使其更加流行。

干杯,