Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find a file that was created within five days of another file in shell

i'm still pretty new to scripting so stick with me and if you have any questions please feel free to ask.

Okay, so: I have a file let's say file.txt

file.txt exists in a directory /this/is/the/directory/file.txt

In a separate directory .log files exist that tell me what happens when file.txt was created.

fuubar.log, fuu.log, bar.log, this.log, that.log, some.log, other.log...there is an unknown number of these logs.

I need to gather all the log files that occurred +-5 days of the file.txt file being created.

For example: file.txt was created on 7 July 2013 (don't pay any attention to date format) I need the log files that occurred on and between 2 July 2013 and 12 July 2013.

Any ideas?

EDIT: I'm more confused about comparing the dates of the files to get the correct ones, i know how to copy files.

Perl and stat are not available to me

like image 921
tc90 Avatar asked Mar 23 '23 03:03

tc90


2 Answers

Well something to get your started unless someone posts a one-liner!

# 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$$
like image 134
jaypal singh Avatar answered Apr 06 '23 04:04

jaypal singh


Since you are on QNX you can't use existing POSIX/Linux/Unix/BSD scripts off the shelf in your approach to this. If you could either install programming languages that can help you do this or install updated system utilities (from QNX one would hope) or shell tools to achieve the same thing it might be easier, but I realize this is not always possible.

You could try the following horrid hackish approach for a quick "works now" solution though:

First use find /path/to/log/file.txt -printf %Cj to give you the day of the year from 1-366 in which the log file was created and -printf %CY to give you the year value. Next use expr +/- 5 as you did before to find values for $day_of_year_start and $day_of_year_end which you can then use to set the $start and $end variables just as in JP's script or my variation on it.

Now you need a way to get epoch time for use with date -s so you can convert from epoch to a time format touch -t will use. Without a date that can convert to and from epoch time and no strftime that outputs epoch time to make this easy, you need a "hack". One messy approach would be to set a constant for the epoch time at the beginning of a year (say 1356998400 for Jan 1 2013 ; plus values for other years if needed) and then add ($day_of_year_start x 86400) and ($day_of_year_end x 86400) seconds to that constant to get two epoch time values to run through date -s on QNX and set a date/timestamp for $start and $end respectively.

Messy but it might actually work :-) Let us know if you try this.

Cheers, ps: here's the start of a script you'll need to check command arguments and date formats for QNX to make sure they are correct. It works on BSD boxes I have with gfind (GNU find) and date -r (instead of date -s for 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 here means Seconds Since Long ago :-)

like image 41
G. Cito Avatar answered Apr 06 '23 03:04

G. Cito