¿Cómo puedo cambiar la marca de tiempo del nombre de archivo?

8

Tengo los nombres de los archivos de datos en orden cronológico:

FileName_YYYY_MM_DD_HHMM.dat

¿Hay algún comando para agregar 30 minutos a cada marca de tiempo?

Strawberrie
fuente
1
¿son esas marcas de tiempo iguales a su fecha de creación? es lo mismo que ls --full-time?
Sergiy Kolodyazhnyy
1
No, las marcas de tiempo son diferentes según su fecha de creación / modificación. Las marcas de tiempo se basan en el tiempo en que se midieron los datos.
Strawberrie
1
Verá, dado que esas marcas de tiempo son personalizadas, requerirá un script, que tiene que calcular agregar 30 minutos a la fecha, no habrá ningún comando simple. por lo que la gente podría tardar un poco en responder
Sergiy Kolodyazhnyy
1
¿Hay alguna marca de tiempo que esté cerca de la medianoche, de modo que agregar 30 minutos puede hacer que sea necesario cambiar un día por uno?
Sergiy Kolodyazhnyy
1
¿Qué formato son las horas? 12 luego 1,2,3 (formato de 12 horas) o 12 a 13 a 14, 15. . . 23, 00 (formato de 24 horas)?
Sergiy Kolodyazhnyy

Respuestas:

6

Utilizando 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')cambiará el directorio actual al directorio que contiene los .datarchivos. Reemplazar /path/to/dircon la ruta real.

  • glob.glob('*.dat') encontrará los archivos que terminan en .dat

  • ini_timeLa variable al principio recortará la fecha y hora del nombre del archivo original usando el remódulo y luego clasificará qué entrada representa qué en la cadena se extrae para que podamos agregar el tiempo requerido a esto

  • fin_timecontendrá el tiempo resultante, es decir, ini_timemás 30 minutos

  • os.rename cambiará el nombre del archivo en consecuencia.

También tenga en cuenta que, con los nombres de archivo sucesivos (diferidos en 30 minutos), el archivo renombrado sobrescribirá el siguiente, por lo tanto, es mejor agregar los segundos al nombre del archivo renombrado para que permanezca seguro. De lo contrario, debe guardar los archivos renombrados en un directorio diferente y luego reemplazarlos con los originales más adelante.

heemayl
fuente
Tú y Python, un gran amor. =) +1
AB
No debe usar la cadena Filename_en el método de cambio de nombre.
AB
@AB ¿Por qué es eso? (+1 para ti también)
heemayl
¿Sabes por qué me faltan algunos archivos después de ejecutar el script de Python? La marca de tiempo para cada archivo tiene una diferencia de 30 minutos. A continuación se muestra la salida para los primeros nombres de archivo: Filename_2011_01_11_1630.dat Filename_2011_01_11_1830.dat Filename_2011_01_11_1900.dat Filename_2011_01_11_2030.dat Filename_2011_01_11_2100.dat
strawberrie
@strawberrie No lo sé ... lo he probado y funciona bien para mí sin ningún problema ... ¿has ejecutado el script reemplazando el /path/to/filecon la ruta completa al directorio?
heemayl
2

Utilizando bash, los archivos renombrados están en una nueva subcarpeta renamed.

Inicie el script en la carpeta donde se encuentran los archivos.

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

salida de ejemplo:

% 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
fuente
@strawberrie los archivos renombrados ahora se colocan en una subcarpetarenamed
AB
Es una buena idea guardar los archivos renombrados en una carpeta adicional. En caso de que algo salga mal, OP todavía tiene originales. Buen pensamiento, por lo tanto +1
Sergiy Kolodyazhnyy
Gracias @AB Tengo el siguiente error después de ejecutar la secuencia de comandos: TimeChange.sh: 21: TimeChange.sh: Bad sustitución Mi nombre real o el prefijo fijo antes de que la marca de tiempo es como FileName_123.Data_YYYY_MM_DD_HHMM.dat
strawberrie
Por definición, para FileName_123.Data_YYYY_MM_DD_HHMM.datla parte .Data_YYYY_MM_DD_HHMM.dates la extensión. Y, por FileName_123lo tanto, no es una marca de tiempo válida.
AB
@strawberrie Tengo mi script cambiado
AB
1

GUIÓN

Esta es la versión editada de mi guión original. OP originalmente no proporcionó información completa sobre el formato de nombres. Este script se adapta a lo que OP mencionó en los comentarios fue el nombre correcto del archivo.

*Notas técnicas: *

En este script separamos el nombre del archivo en 6 campos separados usando awk, con guión bajo como delimitador de campo. Los primeros dos campos, $ 1 y $ 2 se consideran cadenas de texto estático. Los campos 3,4,5 y 6 son la marca de tiempo en la que se muestrearon los datos de OP, no la fecha de creación del archivo en el sistema de archivos.

La variable COPYDIR contiene el nombre del nuevo directorio donde irán los archivos con marca de tiempo actualizada. Creamos ese directorio en el directorio de trabajo actual conmkdir $COPYDIR

Las variables TEXTSTRING y DATESTRING contienen texto estático y marca de tiempo respectivamente. En la salida de muestra a continuación, he usado dos cadenas diferentes para demostrar que el script funcionará independientemente de qué texto contengan los dos primeros campos.

NEWEPOCHTIME es una variable que contiene la nueva marca de tiempo calculada en formato de época unix. NEWDATE es una variable que contiene la marca de tiempo convertida de unix epoch al formato AAAA-MM-DD HH: MM. NEWAPPEND es la marca de tiempo real que se agregará al archivo en el formato deseado de OP AAAA_MM_DD_HHMM.

cp $file "$COPYDIR"/"%TEXTSTRING""$NEWAPPEND".dat copia el archivo antiguo en el directorio "convert_files" (en lugar de moverlo, para evitar la pérdida de datos) con el sello de datos actualizado.

Aviso , el guión va a funcionar siempre y cuando el formato de nombre es muy seguido, es decir, todos los archivos están realmente tienen SomeText_123.Data_YYYY_MM_DD_HHMM.datformato.

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

GUIÓN EN ACCIÓN

La demostración a continuación es una copia directa desde mi terminal. Tenga en cuenta que he creado archivos originales con dos cadenas diferentes en los dos primeros campos. Por lo tanto, este script debería funcionar sin importar el principio del nombre del archivo, siempre que solo haya dos cadenas separadas por un guión bajo

El guión fue nombrado notes-conversionporque desarrollé el guión a partir de las notas que tomé mientras trabajaba en esta pregunta.

Observe que los nombres de archivo que tienen la parte HHMM como 2345 (que es 15 minutos antes de la medianoche) se actualizan a 0015, y la parte DD se actualiza al día siguiente. Formato de 24 horas preservado.

Además, debido a que for loop solo busca .datarchivos, evitamos cambiar el nombre de otros archivos o directorios que pueden estar en el directorio de trabajo, evitando así cualquier pérdida potencial de datos. En el siguiente ejemplo, el directorio original contiene 11 elementos, 3 de los cuales son *.txtarchivos para probar, por lo que solo trabajamos con 8 .datarchivos. En el directorio donde van los archivos actualizados, vemos 8 archivos, todos .daty ningún otro archivo. Los datos están seguros, el script hace su trabajo.

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

EXPLICACIÓN (de la publicación original)

*) Hoy he aprendido que los sistemas Unix-Linux cuentan el tiempo en la época de la época , o simplemente ponen segundos.

*) el script toma cada nombre de archivo, extrae la fecha, la convierte en época, agrega 1800 segundos (que son exactamente 30 minutos) y guarda el archivo con una nueva marca de tiempo.

*) Este script aborda lo que OP quería: cambiar la marca de tiempo en el nombre del archivo, no actualizar el tiempo de creación del archivo en sí

Herramientas utilizadas:

  • ubuntu 15.04

  • GNU bash 4.3.30

  • GNU awk 4.1.1

  • fecha (GNU coreutils) 8.23

Sergiy Kolodyazhnyy
fuente
por cierto, ls | wc -l antes da 36 archivos, y después del script también 36 archivos, ninguno falta
Sergiy Kolodyazhnyy
Además, la razón por la que uso el archivo stat -c% n, es porque analizar la salida de ls no es una buena idea, en general. Algunas personas utilizan findcomandos, lo que también es bueno.
Sergiy Kolodyazhnyy
Gracias @Serg. No sé por qué me fui solamente 2 de cada 727 archivos que quedan en la carpeta después de ejecutar la secuencia de comandos ...
strawberrie
¿Hubo alguna diferencia entre los nombres de archivo reales y el ejemplo que publicó?
Sergiy Kolodyazhnyy
Además, ¿ejecutó la primera línea del "Script en acción"? el rm * era para limpiar mi propio directorio y luego crear un montón de archivos de prueba con diferentes fechas en los nombres de archivo. No se suponía que ejecutaras eso
Sergiy Kolodyazhnyy
-1

Puede usar este código para hacer lo que necesita asumiendo

  1. debe hacer una copia de seguridad y probar el código primero para ver si es adecuado para su caso
  2. estás usando el formato 24H
  3. no se nombrarán archivos después de las 23:29 (si tiene archivos después de ese tiempo, el código debe modificarse para cambiar la fecha también)

el código es:

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 ;

Cómo funciona: el código verificará la parte de minutos en el nombre del archivo, MMluego, si es inferior a 30, agregará 30 a MMsi es igual a 30 o más, agregará 1 hora a la HHparte en el nombre y deducirá 30 minutos del MMparte del nombre

Mente gorda
fuente
para abajo votante por favor notifique la razón?
Fat Mind