Summary: The most complete solution is the last one, choose the one that suits you best depending on what exactly you want to do.
Actually, if all you want is to keep one file per month, you could just rename all files month
. This will overwrite everything but one file per month. You have given no information about what type of file or where these files are. I am assuming that all files are in the same directory and there are no sub directories. If this is wrong, please update your question giving more details and I'll update my answer.
for file in *; do
month=$(date -d `stat -c %y $file | cut -f 1 -d ' ' ` +%B);
mv $file $month;
done
The script above will leave you with files named January
, February
etc. If you need to keep the original file names, you could try this:
for file in *; do
month=$(date -d `stat -c %y $file | cut -f 1 -d ' ' ` +%B);
rm *.$month;
mv $file $file.$month;
done
This will leave you with files called <FILENAME>.<MONTH>
, for example foo.January
.
Both solutions above are very simplistic. A more general solution that will also work on files in sub directories and skips files that are less than a month old is:
find . -type f -mtime +29 | while IFS= read -r file; do
month=$(date -d `stat -c %y "$file" | cut -f 1 -d ' ' ` +%B);
find . -type f -name "*$month" -delete
mv "$file" "$file.$month";
done
NOTES:
The solution above will look for files that are at least a month old in the current directory and all sub directories and will only keep one file per month. This means that if you have two files that were last modified in January, one of which is ./foo
and the other baz/bar
, only one will be kept, either ./foo.January
or baz/bar.January
.
This assumes that you don't have any files from last year that can be named foo.January
. If you do, those will be deleted.
Finally, a slightly more complex one that will let you keep the names of the files unchanged and avoids the problems mentioned above:
tmp=`mktemp -u XXXX`;
find . -type f -mtime +29 | while IFS= read -r file; do
date=$(date -d `stat -c %y "$file" | cut -f 1 -d ' ' ` +%B%Y);
foo=$tmp"_"$date;
find . -type f -name "*$foo" -delete
mv "$file" "$file.$foo";
done
find . -type f -name "*$tmp*" | while IFS= read -r file; do
mv "$file" "${file%.*}";
done
EXPLANATION:
This script uses mktemp -u XXXX
(eg Xy12
) to generate a random string which is then combined with the date (eg January2008
) of the file. All files that are at least a month (>29 days, sorry February) old are then renamed to filename.Xy12_January2008
. The second loop finds all files whose name contains the random string (Xy12
) and removes their extension, so filename.Xy12_January2008
becomes filename
again.
The final result is one file from each month of each year, with the original file name unchanged. The script can deal with file names with spaces and it will find files in the current directory and all sub directories.
file_2013-07-16.txt
or something similar? Linux doesn't store the creation date of files (unless you're using some obscure file system), so unless you've recorded their creation dates in the filenames (or some filetype-specific metadata, or maybe a database), you'll have to do it based off of when they were last edited, rather than when they were created.