How can I change the filename timestamp?
Solution 1:
Using python
:
#!/usr/bin/env python2
import glob, re, os, datetime
os.chdir('/path/to/dir')
for f in glob.glob('*.dat'):
ini_time = datetime.datetime.strptime(re.search(r'(?<=_)(?:\d|_)+(?=.dat$)', f).group(), '%Y_%m_%d_%H%M')
fin_time = (ini_time + datetime.timedelta(minutes=30)).strftime('%Y_%m_%d_%H%M%S')
os.rename(f, 'Filename_' + str(fin_time) + '.dat')
os.chdir('/path/to/dir')
will change the current directory to the directory containing the.dat
files. Replace/path/to/dir
with the actual path.glob.glob('*.dat')
will find the files ending in.dat
ini_time
variable will at first cut out the date-time from the original file name usingre
module and then sort out which entry represents what in the string that is taken out so that we can add the required time to thisfin_time
will contain the resultant time i.e.ini_time
plus 30 minutesos.rename
will rename the file accordingly.
Also note that, with successive file names (differed by 30 minutes) the renamed file will overwrite the next one, hence it it is better to add the seconds to the renamed file name so that it remains safe. Otherwise you need to save the renamed files to a different directory and then replace them with the original ones later.
Solution 2:
Using bash
, the renamed files are in a new sub folder renamed
.
Start the script in the folder where the files are located.
#!/bin/bash
mkdir -p renamed
# loop over all dat files in the current folder
for f in *.dat; do
# the filename without extension
filename="${f%%.*}"
# your timestamp
old_timestamp=$(echo $filename | grep -P "[0-9]{4}_[0-9]{2}_[0-9]{2}_[0-9]{4}$")
if [ "$old_timestamp" == "" ]; then
>&2 echo "not a valid filename: '$f', skipped."
else
# a valid date from the timestamp
new_date=$(echo "$old_timestamp" | awk -F_ '{HM=NF; D=NF-1; M=NF-2; Y=NF-3; print $Y "-" $M "-" $D " " substr($HM,1,2) ":" substr($HM,3,2) ":00"}')
# the new time stamp, 30 mins in the future
changed_timestamp=$(date --date "$new_date 30 minutes" "+%Y_%m_%d_%H%M")
# copy the file, ${f##*.} is the extension
cp "$f" renamed/"${filename/$old_timestamp/$changed_timestamp.${f##*.}}"
fi
done
example output:
% ls -og FileName*
-rw-rw-r-- 1 0 Mai 16 20:35 FileName_2015_05_16_2235.dat
% ./timestamp
% ls -og renamed/FileName*
-rw-rw-r-- 1 0 Mai 16 20:35 FileName_2015_05_16_2305.dat
Solution 3:
SCRIPT
This is the edited version of my original script. OP originally didn't provide full information about the naming format. This script adapts to what OP mentioned in the comments was the correct file naming.
*Technical notes: *
In this script we separate filename into 6 separate fields using awk, with underscore as field delimiter. First two fields , $1 and $2 are considered static text string. Fields 3,4,5, and 6 are the timestamp at which OP's data was sampled, not the file's creation date on the filesystem.
Variable COPYDIR holds name of new directory where files with updated timestamp will go. We create that directory in current working directory with mkdir $COPYDIR
Variables TEXTSTRING and DATESTRING hold static text and timestamp respectivelly. In the sample output bellow I have used two different strings to prove that script will work regardless of what text the first two fields hold.
NEWEPOCHTIME is variable that holds calculated new timestamp in unix epoch format. NEWDATE is variable that holds converted timestamp from unix epoch to YYYY-MM-DD HH:MM format. NEWAPPEND is the actual timestamp that will be added to the file in OP's desired YYYY_MM_DD_HHMM format.
cp $file "$COPYDIR"/"%TEXTSTRING""$NEWAPPEND".dat
copies the old file into "converted_files" directory ( instead of moving, to prevent data loss) with the updated datastamp.
Notice, the script will work as long as the naming format is really followed, i.e., all the files are really have SomeText_123.Data_YYYY_MM_DD_HHMM.dat
format.
#!/usr/bin/env bash
#
# Author: Serg Kolo
# Description: this script takes timestamp within the filename
# (which may be different from file's actual creation date)
# converts that date and time to unix's epoch time
# adds 30 minutes to it and renames it
COPYDIR="converted_files"
mkdir $COPYDIR
for file in *.dat; do
TEXTSTRING=$(stat -c %n $file | awk -F'_' '{print $1"_"$2"_"}' )
DATESTRING=$( stat -c %n $file | awk -F'_' '{gsub(".dat",""); print $3"-"$4"-"$5" "$6}' )
NEWEPOCHTIME=$( expr $( date --date="$DATESTRING" +%s ) + 1800 )
NEWDATE=$(date --date=@"$NEWEPOCHTIME" +%F"_"%R)
NEWAPPEND=$(echo $NEWDATE | awk '{gsub("-","_");gsub(":","");print}')
cp $file "$COPYDIR"/"$TEXTSTRING""$NEWAPPEND".dat
done
SCRIPT IN ACTION
The demonstration bellow is direct copy from my terminal. Notice that I've created original files with two different strings in the first two fields. So this script should work no matter what is in the beginning of the filename, as long as there are really only two strings separated by underscore
The script was named notes-conversion
because I developed the script from the notes I took while working on this question.
Notice that filenames which have HHMM part as 2345 (which is 15 minutes before midnight) get updated to 0015, and DD part is updated to next day. 24 hour format preserved.
In addition, because for loop only looks for .dat
files, we avoid renaming other files or directories that may happen to be in the working directory, thus avoiding any potential data loss. In the example bellow, original directory holds 11 items, 3 of which are *.txt
files for testing, so we only work with 8 .dat
files. In the directory where updated files go, we see 8 files, all .dat
and no other files. Data is safe, script does its job.
[68 ]SERGIY@UBUNTU_[/home/xieerqi/testdir/conversion/convert2]
***********************************************
85 $ ls
FileName_123.Dat_2015_05_31_1245.dat Test.txt
FileName_123.Dat_2015_05_31_2345.dat YoloSwag_123.Dat_2015_05_31_1245.dat
FileName_Foo.Bar_2015_05_31_1245.dat YoloSwag_123.Dat_2015_05_31_2345.dat
FileName_Foo.Bar_2015_05_31_2345.dat YoloSwag_Foo.Bar_2015_05_31_1245.dat
File.txt YoloSwag_Foo.Bar_2015_05_31_2345.dat
Random.txt
[68 ]SERGIY@UBUNTU_[/home/xieerqi/testdir/conversion/convert2]
***********************************************
86 $ ls | wc -l
11
[68 ]SERGIY@UBUNTU_[/home/xieerqi/testdir/conversion/convert2]
***********************************************
87 $ notes-conversion
[68 ]SERGIY@UBUNTU_[/home/xieerqi/testdir/conversion/convert2]
***********************************************
88 $ ls converted_files/; ls converted_files/ | wc -l
FileName_123.Dat_2015_05_31_1315.dat YoloSwag_123.Dat_2015_05_31_1315.dat
FileName_123.Dat_2015_06_01_0015.dat YoloSwag_123.Dat_2015_06_01_0015.dat
FileName_Foo.Bar_2015_05_31_1315.dat YoloSwag_Foo.Bar_2015_05_31_1315.dat
FileName_Foo.Bar_2015_06_01_0015.dat YoloSwag_Foo.Bar_2015_06_01_0015.dat
8
[67 ]SERGIY@UBUNTU_[/home/xieerqi/testdir/conversion/convert2]
***********************************************
89 $
EXPLANATION (from original post)
*) Today I've learned that Unix-Linux systems count time in Epoch time, or simply put seconds.
*) the script takes each file name, extracts date, converts it to epoch , adds 1800 seconds (which is exactly 30 minutes), and saves the file with than new timestamp.
*) This script addresses what OP wanted - change timestamp in filename, not update creation time of the file itself
Tools used:
ubuntu 15.04
GNU bash 4.3.30
GNU awk 4.1.1
date (GNU coreutils) 8.23