Listing files older than 30 days

Hi,

Could someone help me that what the problem is in this code?

#!/bin/sh 

FOLDER=/abc/datasource/checkstatus
 
TIMESTAMP=$(date +%s) 

for filename in $(find $FOLDER -maxdepth 1 -type f -name "CHECK_STATUS*"); do

f1=$($filename -Eo "[0-9]{4}[0-9-]+")

f2=$(date -d "$f1" +%s)

if $TIMESTAMP-$f2 -gt 2592000; then 

echo $(basename "$filename")

fi

done

exit 0;

Thank you.

Wow :eek:

Before I try to work with it, have you considered using the -mtime flag on find? It might save you a lot of effort.

Kind regards,
Robin

What do you think yourself what the errors might be? What error messages did your shell issue when you tried to run the code? Did you try? Did you consider the -x option running it?

Yes, I've tested with -mtime and it works fine. but sometime we are moving files to other folder and then the -mtime doesn't work to list them, then the best way is to extract the date from filename.

It would be helpful if you post a few CHECK_STATUS* entries to examine.
It would be helpful if you post what the errors are. You can post the output of the code running with the flag -x.
It would be helpful if you post the os and shell type you are using.

for filename in $(find $FOLDER -maxdepth 1 -type f -name "CHECK_STATUS*");
f1=${$filename -Eo "[0-9]{4}[0-9-]+"} 

Take a look how Parameter substitution works.

if TIMESTAMP-$f2 > 2592000; then 

Take a look at arithmetic expressions

1 Like

I changed some part of the code but the for loop shows all files and not those that are older than 30 days and also the result for $(TIMESTAMP-$f2) is the same for all file name that is listed, here is an example of output:

./list.sh: line 11: /abc/datasource/checkstatus/CHECK_STATUS_PARTY_CODE_2017-08-31_114506.txt: Permission denied
./list.sh: line 15: 1508845131-1508796000: command not found
./list.sh: line 15: command not found
./list.sh: line 11: /abc/datasource/checkstatus/CHECK_STATUS_PARTY_CHANGE_2017-10-17_114526.txt: Permission denied
./list.sh: line 15: 1508845243-1508796000: command not found

---------- Post updated at 07:08 AM ---------- Previous update was at 06:41 AM ----------

I've changed the code before reading your comments :slight_smile:
but I ran the code with ./list.sh -x and results were the same.

Would you prefer to re-write this as Perl, or can you alter the f1= statement to meet your needs?

If you say something like "It doesn't work" without the current code, input, output & error messages it can be extremely hard to follow through. Can you help us out here?

Please paste them in CODE tags. The tutorial is below:-

Kind regards,
Robin

If people only knew what line 11 and 15 were...

-x is not an option to the script but to the shell running the script. Either use set -x or sh -x scriptname .

Don't be that economical with facts about your setup, and, please, read entire posts and answer ALL the questions asked...

1 Like

Thank you all for your replies. I copied the code in notepad++ and here is the lines for code:

line1 #!/bin/sh 
line2
line3 FOLDER=/abc/datasource/checkstatus
line4 
line5 TIMESTAMP=$(date +%s) 
line6
line7 for filename in $(find $FOLDER 
line8
line9 -maxdepth 1 -type f -name "CHECK_STATUS*"); do
line10
line11 f1=$($filename -Eo "[0-9]{4}[0-9-]+") 
line12
line13 f2=$(date -d "$f1" +%s)
line14
line15 if $"$TIMESTAMP-$f2" -gt 2592000; then 
line16
line17 echo $(basename "$filename")
line18
line19 fi
line20
line21 done
line22
line23 exit 0;

I ran the code with -x option,

bash -x ./list.sh

and here is the results:

-maxdepth 1 -type f -name "CHECK_STATUS*")'
++ /abc/datasource/checkstatus/CHECK_STATUS_BALANCE_2017-10-14_114534.txt -Eo '[0-9]{4}[0-9-]+'
./list.sh: line 11: /abc/datasource/checkstatus/CHECK_STATUS_BALANCE_2017-10-14_114534.txt: Permission denied
+ f1=
++ date -d '' +%s
+ f2=1508882400
+ 1508921365-1508882400 -gt 2592000
./list.sh: line 15: 1508921365-1508882400: command not found
+ for filename in '$(find $FOLDER

-maxdepth 1 -type f -name "CHECK_STATUS*")'
++ /abc/datasource/checkstatus/CHECK_STATUS_CODE_CHECK_2017-09-28_114530.txt-kvitto -Eo '[0-9]{4}[0-9-]+'
./list.sh: line 11: /abc/datasource/checkstatus/CHECK_STATUS_PARTY_2017-09-28_114530.txt: Permission denied
+ f1=
++ date -d '' +%s
+ f2=1508882400
+ 1508921365-1508882400 -gt 2592000
./list.sh: line 15: 1508921365-1508882400: command not found
+ for filename in '$(find $FOLDER

-maxdepth 1 -type f -name "CHECK_STATUS*")'
++ /abc/datasource/checkstatus/CHECK_STATUS_CODE_CHECK_2017-10-07_114714.txt-kvitto -Eo '[0-9]{4}[0-9-]+'
./list.sh: line 11: /abc/datasource/checkstatus/CHECK_STATUS_CHANGE_CHECK_2017-10-07_114714.txt: Permission denied
+ f1=
++ date -d '' +%s
+ f2=1508882400
+ 1508921365-1508882400 -gt 2592000
./list.sh: line 15: 1508921365-1508882400: command not found
+ for filename in '$(find $FOLDER

-maxdepth 1 -type f -name "CHECK_STATUS*")'
++ /abc/datasource/checkstatus/CHECK_STATUS_CODE_CHECK_2017-10-12_114530.txt-kvitto -Eo '[0-9]{4}[0-9-]+'
./list.sh: line 11: /abc/datasource/checkstatus/CHECK_STATUS_CODE_STATUS_CHECK_2017-10-12_114530.txt: Permission denied
+ f1=
++ date -d '' +%s
+ f2=1508882400
+ 1508921365-1508882400 -gt 2592000
./list.sh: line 15: 1508921365-1508882400: command not found
+ for filename in '$(find $FOLDER

---------- Post updated at 04:09 AM ---------- Previous update was at 04:03 AM ----------

CHECK_STATUS are simple files. Name of files are important and you could create a simple text file with the mentioned name.

The results has been posted.

I know the OS is linux, shell type is sh(bash). Please be more specific that what/where I should search.

---------- Post updated at 04:57 AM ---------- Previous update was at 04:09 AM ----------

This part of the code is important to extract the date and rest of the code is somehow depended to it. I don't know how can I remove it and get the result that I want.

We had hoped that you would know that you can't randomly split lines in shell script command lines into multiple lines without breaking the script. (Compare the 3 lines in your script above numbered line7, line8, and line9 with the isingle line in your script in post #1 in this thread:

for filename in $(find $FOLDER -maxdepth 1 -type f -name "CHECK_STATUS*"); do

If you don't understand why there is any difference, type the command:

find . 

into your shell. Then type the command:

-maxdepth 1 -type f -name ".*"

into your shell. (These two commands are roughly equivalent to what you have in the command substitution shown in your script above.) And, then type the command:

find . -maxdepth 1 -type f -name ".*"

into your shell. (Which is roughly equivalent to what you had in post #1 in this thread.) Do you see the difference in the output produced?

In post #5, when Aia said:

he wasn't asking you to show us the contents of those files. He was asking for the format of the naming convention used to name the files. If we have a clear description of the names that will be matched by the pattern CHECK_STATUS* , we can help you make your script MUCH more efficient. From the two names you supplied in later posts:

CHECK_STATUS_PARTY_CHANGE_2017-10-17_114526.txt
CHECK_STATUS_PARTY_CODE_2017-08-31_114506.txt

we might guess that the naming format is something like:

  1. The literal string CHECK_STATUS_ ,
  2. followed by an arbitrary string ending with an underscore character,
  3. followed by a ten character representation of a date in the format YYYY-MM-DD ,
  4. followed by an underscore character,
  5. followed by six decimal digit characters,
  6. followed by the literal string .txt .

If the above is an accurate representation of the rules defining the names of the files you will be processing, there is no need to run find nor is there any need for what I assume was an attempt to run grep -Eo to extract the date from the filename.

You could also speed up your script and make it more efficient by moving into the directory that contains your files instead of processing absolute pathnames and then throwing away the directory hierarchy before printing the filename after determining that your date criteria are met.

If, in addition to the above comments, you also know that all files in the directory /abc/datasource/checkstatus with filenames ending in .txt are regular files, you might want to try the following simpler script to see if it comes close to doing what you want:

#!/bin/sh
cd /abc/datasource/checkstatus || exit
 
S30DAY=$((60*60*24*30))		# Seconds in 30 days.
TIMESTAMP=$(date '+%s')		# Seconds since the Epoch.

for filename in CHECK_STATUS*.txt
do	f1=${filename%_*}	# drop last "_" and everything after it
	f1=${f1##*_}		# drop everything before last "_" and it

	f2=$(date -d "$f1" '+%s')

	[ $((TIMESTAMP - f2)) -gt S30DAY ] && printf '%s\n' "$filename"
done

If all that we know is that the filenames start with the literal string CHECK_STATUS followed by an arbitrary string followed by a date followed by another arbitrary string, we could clean up your script a little bit to something like the following (using grep the way I think you intended to use it):

#!/bin/sh
cd /abc/datasource/checkstatus || exit
 
S30DAY=$((60*60*24*30))		# Seconds in 30 days.
TIMESTAMP=$(date '+%s')		# Seconds since the Epoch.

for filename in CHECK_STATUS*
do
	[ ! -f "$filename" ] && continue

	f1=$(printf '%s\n' "$filename" | grep -Eo '[0-9]{4}-[01][0-9]-[0-3][0-9]')

	f2=$(date -d "$f1" +%s)

	[ $((TIMESTAMP - f2)) -gt S30DAY ] && printf '%s\n' "$filename"
done

-gt will need that to be expanded to an integer.

1 Like

Hi Aia,
Thanks for spotting that.

On the system I'm using, I don't have date -d and the bash on my system doesn't recognize printf '%(%s)T\n' YYYY-MM-DD . Therefore I tested the code I suggested using ksh . And, ksh version 93u+ expands the S30DAY variable in that test statement with or without the dollar sign.

  • Don