Search code examples
bashfindunix-timestampgnu-findutils

Find files in directory modified at various times


Bash newbie here. The task is to find all files in a (rather large) directory whose modification date falls between various pairs of times. These times are specified as Unix timestamps in a CSV file:

1483743420,1483747020
1484348640,1484352240
1484953920,1484957520
1485559200,1485562800
1486164480,1486168080
1486769820,1486773420

My early thought was to use find and awk:

find "$PROJECT_DIR" -type f \
-newermt "$(awk -F "","" '{print $1}' "$DATE_CSV")" -not \
-newermt "$(awk -F "","" '{print $2}' "$DATE_CSV")"

find doesn't seem to recognize this date format. More pressingly, this code only sends the first date to find, and the rest are printed:

$ bash datefind.sh
find: Can't parse date/time: 1483743420
1484348640
1484953920
1485559200
1486164480
1486769820

Is there a way to do this with a single find command? Or should I be trying something else?


Solution

  • With GNU find:

    PROJECT_DIR="/tmp"
    DATE_CSV="file"
    find "$PROJECT_DIR" \( -type f \) -a \( $(awk -F ',' 'NR==1 { print "-newermt @" $1 " -not -newermt @" $2 }; NR!=1 { print "-o -newermt @" $1 " -not -newermt @" $2 }' "$DATE_CSV") \)
    

    From man find:

    -newermt: Time specifications are interpreted as for the argument to the -d option of GNU date.

    -o: logical OR

    -a: logical AND


    What awk does:

    DATE_CSV="file"
    awk -F ',' 'NR==1 { print "-newermt @" $1 " -not -newermt @" $2 }; NR!=1 { print "-o -newermt @" $1 " -not -newermt @" $2 }' "$DATE_CSV"
    

    Output:

    -newermt @1483743420 -not -newermt @1483747020
    -o -newermt @1484348640 -not -newermt @1484352240
    -o -newermt @1484953920 -not -newermt @1484957520
    -o -newermt @1485559200 -not -newermt @1485562800
    -o -newermt @1486164480 -not -newermt @1486168080
    -o -newermt @1486769820 -not -newermt @1486773420