我对脚本还很陌生,所以请继续关注我,如果您有任何问题,请随时提问。
好吧,所以:我有一个文件,比方说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;}
的东西,使其更花哨。
干杯,