Jak mogę zmienić znacznik czasu nazwy pliku?

8

Mam nazwy plików danych w kolejności chronologicznej:

FileName_YYYY_MM_DD_HHMM.dat

Czy są jakieś polecenia dodawania 30 minut do każdego znacznika czasu?

strawberrie
źródło
1
czy te znaczniki czasu są takie same jak data ich utworzenia? czy to to samo co ls --full-time?
Sergiy Kolodyazhnyy
1
Nie, znaczniki czasu różnią się od daty ich utworzenia / modyfikacji. Znaczniki czasu są oparte na czasie, gdy dane zostały zmierzone.
strawberrie
1
Widzisz, ponieważ te znaczniki czasu są niestandardowe, będzie wymagał skryptu, który musi obliczyć dodanie 30 minut do daty, nie będzie żadnego prostego polecenia. więc może trochę potrwać, zanim ludzie odpowiedzą
Sergiy Kolodyazhnyy
1
czy są jakieś znaczniki czasu zbliżające się do północy, tak że dodanie 30 minut może spowodować konieczność zmiany dnia o jeden?
Sergiy Kolodyazhnyy
1
w jakim formacie są godziny? 12 następnie 1,2,3 (format 12-godzinny) lub od 12 do 13 do 14, 15. . . 23, 00 (format 24-godzinny)?
Sergiy Kolodyazhnyy

Odpowiedzi:

6

Używanie 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')zmieni bieżący katalog na katalog zawierający .datpliki. Zamień /path/to/dirna rzeczywistą ścieżkę.

  • glob.glob('*.dat') znajdzie pliki kończące się na .dat

  • ini_timezmienna najpierw wycina datę i czas z oryginalnej nazwy pliku za pomocą remodułu, a następnie sortuje, który wpis reprezentuje to, co w łańcuchu, który jest usuwany, abyśmy mogli dodać do tego wymagany czas

  • fin_timebędzie zawierać wynikowy czas, tj. ini_timeplus 30 minut

  • os.rename odpowiednio zmieni nazwę pliku.

Zauważ też, że przy kolejnych nazwach plików (różniących się o 30 minut) plik o zmienionej nazwie zastąpi następny, dlatego lepiej jest dodać sekundy do nazwy o zmienionej nazwie, aby zachować bezpieczeństwo. W przeciwnym razie należy zapisać pliki o zmienionej nazwie w innym katalogu, a następnie zastąpić je oryginalnymi plikami później.

heemayl
źródło
Ty i python, wielka miłość. =) +1
AB
Nie należy używać łańcucha Filename_w metodzie zmiany nazwy.
AB
@AB Dlaczego tak jest? (+1 dla ciebie)
heemayl
Czy wiesz, dlaczego brakuje niektórych plików po uruchomieniu skryptu python? Znacznik czasu dla każdego pliku ma 30-minutową różnicę. Poniżej znajduje się wynik dla kilku pierwszych nazw plików: Nazwa_pliku_2011_01_11_1630.dat Nazwa pliku_2011_01_11_1830.dat Nazwa pliku_2011_01_11_1900.dat Nazwa pliku_2011_01_11_11_2030.dat Nazwa pliku_2011_01_11_2100.dat
strawberrie
@strawberrie Nie wiem .. przetestowałem go i działa dla mnie bez problemu .. czy uruchomiłeś skrypt zastępując /path/to/filepełną ścieżkę do katalogu?
heemayl
2

Za bashpomocą pliki o zmienionej nazwie znajdują się w nowym podfolderze renamed.

Uruchom skrypt w folderze, w którym znajdują się pliki.

#!/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

przykładowe dane wyjściowe:

% 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
AB
źródło
@strawberrie pliki o zmienionej nazwie są teraz umieszczane w podfolderzerenamed
AB
dobrym pomysłem jest zapisanie plików o zmienionej nazwie w dodatkowym folderze. W przypadku, gdy coś pójdzie nie tak, OP nadal ma oryginały. Dobre myślenie, stąd +1
Sergiy Kolodyazhnyy
Dzięki @AB Po uruchomieniu skryptu dostałem następujący błąd: TimeChange.sh: 21: TimeChange.sh: Złe podstawienie Moja rzeczywista nazwa pliku lub ustalony prefiks przed datownikiem jest podobny do FileName_123.Data_YYYY_MM_DD_HHMM.dat
strawberrie
Zgodnie z definicją dla FileName_123.Data_YYYY_MM_DD_HHMM.datczęści .Data_YYYY_MM_DD_HHMM.datjest rozszerzeniem. I dlatego FileName_123nie jest prawidłowym znacznikiem czasu.
AB
@strawberrie Mam zmieniony skrypt
AB
1

SCENARIUSZ

To jest zredagowana wersja mojego oryginalnego skryptu. OP początkowo nie dostarczył pełnych informacji o formacie nazewnictwa. Ten skrypt dostosowuje się do tego, co OP wspomniane w komentarzach było prawidłowym nazewnictwem plików.

* Uwagi techniczne: *

W tym skrypcie rozdzielamy nazwę pliku na 6 oddzielnych pól za pomocą awk, z podkreślnikiem jako ogranicznikiem pola. Pierwsze dwa pola, 1 $ i 2 $, są traktowane jako ciąg tekstowy. Pola 3,4,5 i 6 to znacznik czasu, w którym próbkowane były dane OP, a nie data utworzenia pliku w systemie plików.

Zmienna COPYDIR zawiera nazwę nowego katalogu, do którego trafią pliki ze zaktualizowanym znacznikiem czasu. Tworzymy ten katalog w bieżącym katalogu roboczym za pomocąmkdir $COPYDIR

Zmienne TEXTSTRING i DATESTRING przechowują odpowiednio tekst statyczny i znacznik czasu. W poniższym przykładzie wyjściowym użyłem dwóch różnych ciągów, aby udowodnić, że skrypt będzie działał niezależnie od tego, jaki tekst zawierają dwa pierwsze pola.

NEWEPOCHTIME jest zmienną, która przechowuje obliczony nowy znacznik czasu w formacie epoki uniksowej. NEWDATE jest zmienną, która przechowuje konwertowany znacznik czasu z epoki uniksowej na format RRRR-MM-DD GG: MM. NEWAPPEND to rzeczywisty znacznik czasu, który zostanie dodany do pliku w pożądanym formacie YYYY_MM_DD_HHMM PO.

cp $file "$COPYDIR"/"%TEXTSTRING""$NEWAPPEND".dat kopiuje stary plik do katalogu „przekonwertowane pliki” (zamiast przenosić, aby zapobiec utracie danych) za pomocą zaktualizowanego znacznika danych.

Wskazówki , skrypt będzie działać tak długo, jak format nazewnictwa jest rzeczywiście następuje, czyli wszystkie pliki są naprawdę mieć SomeText_123.Data_YYYY_MM_DD_HHMM.datformat.

#!/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

PISMO W AKCJI

Poniższa demonstracja jest bezpośrednią kopią z mojego terminalu. Zauważ, że utworzyłem oryginalne pliki z dwoma różnymi ciągami w pierwszych dwóch polach. Więc ten skrypt powinien działać bez względu na to, co jest na początku nazwy pliku, o ile tak naprawdę są tylko dwa ciągi znaków oddzielone znakiem podkreślenia

Skrypt został nazwany, notes-conversionponieważ opracowałem go na podstawie notatek, które sporządziłem podczas pracy nad tym pytaniem.

Zauważ, że nazwy plików, które mają część HHMM jako 2345 (czyli 15 minut przed północą), są aktualizowane do 0015, a część DD jest aktualizowana do następnego dnia. Zachowano format 24-godzinny.

Ponadto, ponieważ dla pętli szuka tylko .datplików, unikamy zmiany nazw innych plików lub katalogów, które mogą znajdować się w katalogu roboczym, co pozwala uniknąć potencjalnej utraty danych. W poniższym przykładzie oryginalny katalog zawiera 11 elementów, z których 3 to *.txtpliki do testowania, więc pracujemy tylko z 8 .datplikami. W katalogu, do którego trafiają zaktualizowane pliki, widzimy 8 plików, wszystkie .dati żadnych innych plików. Dane są bezpieczne, skrypt spełnia swoje zadanie.

[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 $ 

WYJAŚNIENIE (z oryginalnego postu)

*) Dzisiaj dowiedziałem się, że systemy Unix-Linux liczą czas w epoce lub po prostu umieszczają sekundy.

*) skrypt pobiera każdą nazwę pliku, wyodrębnia datę, konwertuje ją do epoki, dodaje 1800 sekund (dokładnie dokładnie 30 minut) i zapisuje plik z nową datą.

*) Ten skrypt dotyczy tego, czego chciał OP - zmień znacznik czasu w nazwie pliku, a nie aktualizuj czasu utworzenia samego pliku

Narzędzia użyte:

  • ubuntu 15.04

  • GNU bash 4.3.30

  • GNU awk 4.1.1

  • data (GNU coreutils) 8.23

Sergiy Kolodyazhnyy
źródło
tak przy okazji, ls | wc -l przed daje 36 plików, a po skrypcie także 36 plików, żadnych brakujących
Sergiy Kolodyazhnyy
Ponadto powodem, dla którego używam pliku stat -c% n, jest to, że parsowanie danych wyjściowych ls nie jest ogólnie dobrym pomysłem. Niektórzy ludzie używają findpolecenia, co jest również dobre.
Sergiy Kolodyazhnyy
Dzięki @erg. Nie wiem, dlaczego po uruchomieniu skryptu zostawiłem tylko 2 z 727 plików w folderze ...
strawberrie
Czy była jakaś różnica między rzeczywistymi nazwami plików a zamieszczonym przykładem?
Sergiy Kolodyazhnyy
czy uruchomiłeś pierwszą linię w „Skrypcie w akcji”? rm * służył do czyszczenia własnego katalogu, a następnie tworzenia wiązki plików testowych z różnymi datami w nazwach plików. Nie miałeś tego prowadzić
Sergiy Kolodyazhnyy
-1

Możesz użyć tego kodu do zrobienia tego, czego potrzebujesz

  1. należy najpierw wykonać kopię zapasową i przetestować kod, aby sprawdzić, czy pasuje on do Twojej sprawy
  2. używasz formatu 24H
  3. żadne pliki nie zostaną nazwane po 23:29 (jeśli masz pliki po tym czasie kod należy zmodyfikować, aby zmienić również datę)

kod to:

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 ;

Jak to działa: kod sprawdzi część minut w nazwie pliku, MMa jeśli jest mniejsza niż 30, doda 30 do, MMjeśli jest równa 30 lub więcej, doda 1 godzinę do HHczęści w nazwie i odejmie 30 minut od MMczęść nazwy

Gruby Umysł
źródło
dla głosujących w dół proszę podać przyczynę?
Fat Mind