4

我对脚本仍然很陌生,所以请坚持我,如果您有任何问题,请随时提问。

好的,所以:我有一个文件,比如说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 ...这些日志的数量未知。

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

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

有任何想法吗?

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

Perl 并且stat对我不可用

4

3 回答 3

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$$
于 2013-07-18T15:52:44.527 回答
2

由于您使用的是 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 的值,然后您可以使用它们来设置$startand$end变量,就像在 JP 的脚本或我的变体中一样。

现在您需要一种方法来获取使用的纪元时间,date -s以便您可以从纪元转换为touch -t将使用的时间格式。如果没有一个date可以在纪元时间之间进行转换并且没有strftime输出纪元时间来使这变得容易的,你需要一个“hack”。一种混乱的方法是在年初为纪元时间设置一个常数(比如 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 find)和date -r (而不是date -sQNX)的 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 这里的意思是很久以前的秒数 :-)

于 2013-07-31T01:33:46.803 回答
1

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

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

您已经告诉我们您正在使用 QNX,因此您的 QNX 版本find将拥有-printf扩展。find这意味着您可以使用+/- 5 天来创建您的值,但不能date -v使用expr. QNX 文档似乎对您如何以一种简单明了的方式做到这一点保持沉默,说明了为什么一种简单的可移植(POSIX shell)方式来获取文件修改时间、设置日期、转换日期格式等会很好在现实世界中有。您需要向 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 脚本的最后一部分已经描述过了。

另一种选择涉及骑跨平台骆驼进行救援的人......就像这样:-)

当然,这可能会更好,但这是一种perlfind2perl输出中抄袭的方法:

#!/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;} 让它更花哨的东西。

干杯,

于 2013-07-18T21:21:42.027 回答