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



我对脚本还很陌生,所以请继续关注我,如果您有任何问题,请随时提问。

好吧,所以:我有一个文件,比方说file.txt

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

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

fuubar.log、fuu.log、bar.log、this.log、that.log、some.log、other.log…这些日志的数量未知。

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

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

有什么想法吗?

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

Perl和stat对我来说不可用

除非有人发布一行代码,否则这是一件很好的事情!

# 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$$

由于您使用的是QNX,因此无法在您的方法中使用现有的POSIX/Linux/Unix/BSD脚本。如果你可以安装可以帮助你做到这一点的编程语言,或者安装更新的系统实用程序(人们希望来自QNX)或shell工具来实现同样的事情,这可能会更容易,但我意识到这并不总是可能的。

不过,你可以尝试以下可怕的黑客方法来快速"立即工作"解决方案:

首先使用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的epoch时间,这样您就可以将epoch转换为touch -t将使用的时间格式。如果没有可以转换为epoch时间和从epoch时间转换的date,也没有输出epoch时间的strftime来简化这一点,你需要一个"破解"。一种混乱的方法是为年初的历元时间设置一个常数(例如,2013年1月1日为1356998400;如果需要,加上其他年份的值),然后将($day_of_eyear_start x 86400)和($day_of_eYear_end x 864000)秒添加到该常数,以获得两个历元时间值,从而在QNX上运行date -s,并分别为$start$end设置日期/时间戳。

混乱,但它可能真的有效:-)如果你尝试这个,请告诉我们。

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

#!/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在这里的意思是自很久以前以来的秒数:-)

通常没有简单的可移植(POSIX)方法来获取文件修改时间。

请注意,如果Unix的find版本包含GNU扩展(如-printf),则可以使用find获取原始日志文件的日期。如果您的date版本不包括用于在时间上前后调整日期字符串的-v,那么您必须找到某种方法将日期转换为Epoch日期(很久以前的秒数),并使用expr(+/-86400*5)调整日期,然后将其转换为可与touch一起使用的格式。

您已经告诉我们您正在使用QNX,因此对于find的QNX版本,您将拥有-printf扩展。这意味着您可以使用find创建您的值,但不能使用date -v将其调整+/-5天,也不能将其转换为Epoch时间以使用expr进行修改。QNX文档似乎没有说明如何以一种简单明了的方式做到这一点,说明了为什么在现实世界中使用一种简单的可移植(POSIXshell)方法来获取文件修改时间、设置日期、转换日期格式等会很好。您需要向QNX专家寻求更多帮助。很抱歉

为了补充JaypalSingh的GNU核心实用程序解决方案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已经描述过了。

另一种选择是有人骑着跨平台的骆驼去营救。。。像这样:-)

当然,这可能要好得多,但这里有一种从find2perl输出中抄袭而来的perl方法:

#!/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("$namen");                                                    
}                                                                           

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

if ($#ARGV != 1) {  # require 2 args (last array index +1)
 usage() ;  
 }

sub wanted运行之前,以及类似sub usage { print "whatever n"; exit;}的东西,使其更花哨。

干杯,

相关内容

  • 没有找到相关文章

最新更新