Как я могу изменить временную метку имени файла?
У меня есть имена файлов в хронологическом порядке:
FileName_YYYY_MM_DD_HHMM.dat
Есть ли команды для добавления 30 минут к каждой отметке времени?
4 ответа
С помощью 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')
изменит текущий каталог на каталог, содержащий.dat
файлы. замещать/path/to/dir
с фактическим путем.glob.glob('*.dat')
найдет файлы, оканчивающиеся на.dat
ini_time
переменная будет сначала вырезать дату и время из исходного имени файла, используяre
модуль, а затем разобраться, какая запись представляет то, что в строке, которая вынимается, чтобы мы могли добавить необходимое время к этомуfin_time
будет содержать результирующее время, т.е.ini_time
плюс 30 минутos.rename
переименует файл соответственно.
Также обратите внимание, что при последовательных именах файлов (различающихся на 30 минут) переименованный файл будет перезаписывать следующий, поэтому лучше добавить секунды к переименованному имени файла, чтобы он оставался безопасным. В противном случае вам нужно сохранить переименованные файлы в другой каталог, а затем заменить их исходными.
С помощью bash
переименованные файлы находятся в новой подпапке renamed
,
Запустите скрипт в папке, где находятся файлы.
#!/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
пример вывода:
% 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
SCRIPT
Это отредактированная версия моего оригинального сценария. Первоначально ОП не предоставил полную информацию о формате имен. Этот сценарий адаптируется к тому, что OP, упомянутый в комментариях, был правильным именованием файлов.
* Технические примечания: *
В этом сценарии мы разделяем имя файла на 6 отдельных полей, используя awk, с подчеркиванием в качестве разделителя полей. Первые два поля, $1 и $2, считаются статической текстовой строкой. Поля 3,4,5 и 6 - это отметка времени, в которую были взяты данные OP, а не дата создания файла в файловой системе.
Переменная COPYDIR содержит имя нового каталога, куда будут отправляться файлы с обновленной отметкой времени. Мы создаем этот каталог в текущем рабочем каталоге с mkdir $COPYDIR
Переменные TEXTSTRING и DATESTRING содержат статический текст и метку времени соответственно. В приведенном ниже примере вывода я использовал две разные строки, чтобы доказать, что скрипт будет работать независимо от того, какой текст содержат первые два поля.
NEWEPOCHTIME - это переменная, которая содержит вычисленную новую временную метку в формате эпохи Unix. NEWDATE - это переменная, которая содержит конвертированную метку времени из эпохи Unix в формат ГГГГ-ММ-ДД ЧЧ: ММ. NEWAPPEND - это фактическая временная метка, которая будет добавлена в файл в желаемом формате OP YYYY_MM_DD_HHMM.
cp $file "$COPYDIR"/"%TEXTSTRING""$NEWAPPEND".dat
копирует старый файл в каталог "convert_files" (вместо перемещения, чтобы предотвратить потерю данных) с обновленной меткой данных.
Обратите внимание, что скрипт будет работать до тех пор, пока формат имен действительно соблюдается, т. Е. Все файлы действительно имеют SomeText_123.Data_YYYY_MM_DD_HHMM.dat
формат.
#!/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
СЦЕНАРИЙ В ДЕЙСТВИИ
Демонстрация ниже - прямая копия с моего терминала. Обратите внимание, что я создал оригинальные файлы с двумя разными строками в первых двух полях. Таким образом, этот сценарий должен работать независимо от того, что находится в начале имени файла, если на самом деле только две строки разделены подчеркиванием
Сценарий был назван notes-conversion
потому что я разработал сценарий из заметок, которые я сделал, работая над этим вопросом.
Обратите внимание, что имена файлов, которые имеют часть ЧЧММ как 2345 (то есть за 15 минут до полуночи), обновляются до 0015, а часть DD обновляется до следующего дня. 24-часовой формат сохранен.
Кроме того, поскольку цикл ищет только .dat
файлы, мы избегаем переименования других файлов или каталогов, которые могут оказаться в рабочем каталоге, что позволяет избежать любой потенциальной потери данных. В приведенном ниже примере оригинальный каталог содержит 11 элементов, 3 из которых *.txt
файлы для тестирования, поэтому мы работаем только с 8 .dat
файлы. В каталоге, где находятся обновленные файлы, мы видим 8 файлов, все .dat
и никаких других файлов. Данные в безопасности, скрипт выполняет свою работу.
[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 $
ОБЪЯСНЕНИЕ (из оригинального поста)
*) Сегодня я узнал, что системы Unix-Linux считают время в эпоху, или, проще говоря, секунды.
*) скрипт берет каждое имя файла, извлекает дату, преобразует ее в эпоху, добавляет 1800 секунд (что составляет ровно 30 минут) и сохраняет файл с новой отметкой времени.
*) Этот скрипт обращается к тому, что хотел OP - изменяет временную метку в имени файла, а не обновляет время создания самого файла
Используемые инструменты:
Ubuntu 15.04
GNU bash 4.3.30
GNU awk 4.1.1
дата (GNU coreutils) 8,23
Вы можете использовать этот код, чтобы делать то, что вам нужно, предполагая,
- Вы должны сначала сделать резервную копию и протестировать код, чтобы увидеть, подходит ли он для вашего случая
- вы используете формат 24H
- никакие файлы не будут названы после 23:29 (если у вас есть файлы после этого времени, необходимо изменить код, чтобы изменить дату)
код:
cd /path/to/the/files
for i in `ls`; do MM=${i:(-6): -4}; HH=${i: -8 : -6 }; NAME=${i: 0 : -8 } ; if [ "$MM" -lt 30 ] ; then NEWMM=$((10#$MM+30)); mv -f $i $NAME$HH$NEWMM.dat ; else NEWHH=$((10#$HH+1));NEWMM=$((10#$MM-30)) ; mv -f $i $NAME$NEWHH$NEWMM.dat ; fi ; done ;
Как это работает: код будет проверять часть минут в имени файла MM
тогда, если это меньше 30, это добавит 30 к MM
если он равен 30 или более, это добавит 1 час к HH
часть имени и вычесть 30 минут из MM
часть имени