Imprimir la última fecha de modificación de un archivo en Bash

147

Parece que no puedo encontrar cómo imprimir la fecha de un archivo. Hasta ahora puedo imprimir todos los archivos en un directorio, pero necesito imprimir las fechas con él.

Sé que necesito adjuntar un formato de fecha con el eco de la entrada, pero no puedo encontrar el formato correcto.

echo "Please type in the directory you want all the files to be listed"

read directory 

for entry in "$directory"/*
do
  echo "$entry"
done
Hokerie
fuente
2
lee -p "Por favor, escribe el directorio en el que deseas que
aparezcan

Respuestas:

146

Puedes usar el stat comando

stat -c %y "$entry"

Más información

% y tiempo de la última modificación, legible por humanos
Steven Penny
fuente
for entry in "$directory"/* do stat -c%y "$entry" done No funciona Imprime estadística: operando perdido en la terminal
Hokerie
Hm, ¿podría ser mi unbuntu? ¿Sabes cuáles son los requisitos de uso stat?
Hokerie
33
Tenga en cuenta que en OS X (Mac), es stat -f "%m%t%Sm %N" filename(ver man stat ejemplos para más detalles)
Olie
3
Tenga en cuenta que en BSD el statcomando tiene una sintaxis diferente. Mi caso de FreeBSD: stat -f %Sm -t %F" "%R filename.
Sopalajo de Arrierez
229

¿No es el comando 'date' mucho más simple? No hay necesidad de awk, stat, etc.

date -r <filename>

Además, considere buscar en la página del manual el formato de fecha; por ejemplo con formato común de fecha y hora:

date -r <filename> "+%m-%d-%Y %H:%M:%S"
mmond
fuente
11
Mucho más simple que usar stat / more disponible.
Ing
11
Parece que BSD (o al menos OS X's) dateno tiene esto. Su -rsólo se utiliza para proporcionar una marca de tiempo a formato. Tendrá que usar la fecha GNU para obtener esta funcionalidad.
Waleed Khan
44
Sobre el uso de OSX: fechastat -f "%Sm" -t "%m%d%H%M%y" "${1}"
Michaelangel007
3
En OS X 10.10 date -r <nombre de archivo> funciona como se anuncia, aunque la página del manual no describe ningún argumento <nombre de archivo>.
gotofritz
3
En macOS 10.13 date [-r seconds | filename]está completamente documentado en la manpágina y funciona como se esperaba.
Echelon
14

En OS X, me gusta que mi fecha esté en el formato de YYYY-MM-DD HH:MMla salida para el archivo.

Entonces, para especificar un archivo que usaría:

stat -f "%Sm" -t "%Y-%m-%d %H:%M" [filename]

Si quiero ejecutarlo en un rango de archivos, puedo hacer algo como esto:

#!/usr/bin/env bash
for i in /var/log/*.out; do
  stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$i"
done

Este ejemplo se imprimirá la última vez que ejecuté el sudo periodic daily weekly monthlycomando, ya que hace referencia a los archivos de registro.


Para agregar los nombres de archivo en cada fecha, ejecutaría lo siguiente en su lugar:

#!/usr/bin/env bash
for i in /var/log/*.out; do
  stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$i"
  echo "$i"
done

El resultado sería el siguiente:

2016-40-01 16:40
/var/log/daily.out
2016-40-01 16:40
/var/log/monthly.out
2016-40-01 16:40
/var/log/weekly.out

Desafortunadamente, no estoy seguro de cómo evitar el salto de línea y mantener el nombre del archivo adjunto al final de la fecha sin agregar más líneas al script.


PD: lo uso #!/usr/bin/env bashcomo usuario de Python por día, y tengo diferentes versiones bashinstaladas en mi sistema en lugar de#!/bin/bash

Danijel-James W
fuente
En caso de que no haya descubierto la parte del salto de línea, el indicador -e está disponible para el programa de eco. Ejemplo de uso podría ser: echo -e "$(stat -f %Sm -t %Y%m%d_%H%M%S $AFile)\t$AFile.". En su caso, podría ser: echo -e "$(stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$i")\t$i." `
Thoth
14

Lo mejor es

date -r filename +"%Y-%m-%d %H:%M:%S"
rishi
fuente
Esta respuesta es un duplicado de stackoverflow.com/a/20807343/6320039
Ulysse BN
@UlysseBN no, es un poco diferente. Él aboga por un mejor formato de fecha.
iconoclasta
6

Agregando a la respuesta @StevePenny, es posible que desee cortar la parte no tan legible para los humanos:

stat -c%y Localizable.strings | cut -d'.' -f1
fotanus
fuente
3

Quería obtener la fecha de modificación de un archivo en YYYYMMDDHHMMSSformato. Así es como lo hice:

date -d @$( stat -c %Y myfile.css ) +%Y%m%d%H%M%S

Explicación. Es la combinación de estos comandos:

stat -c %Y myfile.css # Get the modification date as a timestamp
date -d @1503989421 +%Y%m%d%H%M%S # Convert the date (from timestamp)
Fabien Snauwaert
fuente
2

EDITADO: resulta que había olvidado las comillas necesarias para $entryimprimir correctamente y no dar el error "no existe tal archivo o directorio". ¡Muchas gracias a todos por ayudarme!

Aquí está mi código final:

    echo "Please type in the directory you want all the files to be listed with last modified dates" #bash can't find file creation dates

read directory

for entry in "$directory"/*

do
modDate=$(stat -c %y "$entry") #%y = last modified. Qoutes are needed otherwise spaces in file name with give error of "no such file"
modDate=${modDate%% *} #%% takes off everything off the string after the date to make it look pretty
echo $entry:$modDate

Se imprime así:

/home/joanne/Dropbox/cheat sheet.docx:2012-03-14
/home/joanne/Dropbox/Comp:2013-05-05
/home/joanne/Dropbox/Comp 150 java.zip:2013-02-11
/home/joanne/Dropbox/Comp 151 Java 2.zip:2013-02-11
/home/joanne/Dropbox/Comp 162 Assembly Language.zip:2013-02-11
/home/joanne/Dropbox/Comp 262 Comp Architecture.zip:2012-12-12
/home/joanne/Dropbox/Comp 345 Image Processing.zip:2013-02-11
/home/joanne/Dropbox/Comp 362 Operating Systems:2013-05-05
/home/joanne/Dropbox/Comp 447 Societal Issues.zip:2013-02-11
Hokerie
fuente
2

Para los saltos de línea, edité su código para obtener algo sin saltos de línea.

#!/bin/bash
for i in /Users/anthonykiggundu/Sites/rku-it/*; do
   t=$(stat -f "%Sm"  -t "%Y-%m-%d %H:%M" "$i")
   echo $t : "${i##*/}"  # t only contains date last modified, then only filename 'grokked'- else $i alone is abs. path           
done
Anton Kiggundu
fuente
1

Si el nombre del archivo no tiene espacios:

ls -l <dir> | awk '{print $6, " ", $7, " ", $8, " ", $9 }'

Esto se imprime con el siguiente formato:

 Dec   21   20:03   a1.out
 Dec   21   20:04   a.cpp

Si los nombres de archivo tienen espacio (también puede usar el siguiente comando para nombres de archivo sin espacios, solo se ve complicado / feo que el anterior):

 ls -l <dir> | awk '{printf ("%s %s %s ",  $6,  $7, $8); for (i=9;   i<=NF; i++){ printf ("%s ", $i)}; printf ("\n")}'
Cuenta
fuente
¡Ah, ya veo! Eso funciona principalmente, excepto los archivos con espacios en los nombres. ¿Hay una solución para eso?
Hokerie
En realidad, lo intenté de nuevo, y no funciona ... resulta que estaba probando un directorio que tenía nombres de archivos sin espacios. = /
Edité
cuando dices que no funciona, ¿puedes decir cuál es el error? funciona para mí cuando lo ejecuté en mi sistema.
Bill
Tengo un "no hay tal archivo o directorio".
Hokerie
Esto se debe a que pasó un valor <dir>que no existe ... el código está perfectamente bien.
Bill
0

Puedes usar:

ls -lrt filename |awk '{print "%02d",$7}'

Esto mostrará la fecha en 2 dígitos.

Si entre 1 y 9 le agrega el prefijo "0" y lo convierte a 01-09.

Espero que esto cumpla con las expectativas.

Yoga Nathan
fuente