Imprimir a data da última modificação de um arquivo no Bash

147

Não consigo encontrar como imprimir a data de um arquivo. Até agora, sou capaz de imprimir todos os arquivos em um diretório, mas preciso imprimir as datas com ele.

Sei que preciso anexar um formato de data com o eco da entrada, mas não consigo encontrar o formato correto.

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
fonte
2
read -p "Digite o diretório em que você deseja que todos os arquivos sejam listados"
CousinCocaine

Respostas:

146

Você pode usar o stat comando

stat -c %y "$entry"

Mais informações

% y tempo da última modificação, legível por humanos
Steven Penny
fonte
for entry in "$directory"/* do stat -c%y "$entry" done Não funciona Imprime estatísticas: faltando operando no Terminal
Hokerie
Hum, poderia ser o meu unbuntu? Você sabe quais são os requisitos de uso stat?
Hokerie
33
Note-se que no OS X (Mac), é stat -f "%m%t%Sm %N" filename(ver man stat exemplos para mais detalhes)
Olie
3
Observe que no BSD o statcomando tem uma sintaxe diferente. Meu caso para o FreeBSD: stat -f %Sm -t %F" "%R filename.
Sopalajo de Arrierez
228

O comando 'date' não é muito mais simples? Não há necessidade de awk, stat, etc.

date -r <filename>

Além disso, considere olhar para a página de manual para formatação de data; por exemplo, com formato comum de data e hora:

date -r <filename> "+%m-%d-%Y %H:%M:%S"
mmond
fonte
11
Muito mais simples do que usar stat / more available.
Ing
11
Parece que o BSD (ou pelo menos OS X) datenão tem isso. É -rusado apenas para fornecer um carimbo de data / hora para formatar. Você precisará usar a data GNU para obter essa funcionalidade.
Waleed Khan1
4
No OSX use: datestat -f "%Sm" -t "%m%d%H%M%y" "${1}"
Michaelangel007
3
No OS X 10.10, a data -r <filename> funciona como anunciado, embora a página de manual não descreva nenhum argumento <filename>.
gotofritz
3
No macOS 10.13, date [-r seconds | filename]está totalmente documentado na manpágina e funciona conforme o esperado.
Echelon
14

No OS X, eu gosto da minha data no formato de YYYY-MM-DD HH:MMsaída do arquivo.

Então, para especificar um arquivo, eu usaria:

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

Se eu quiser executá-lo em vários arquivos, posso fazer algo assim:

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

Este exemplo será impresso na última vez em que executei o sudo periodic daily weekly monthlycomando, que faz referência aos arquivos de log.


Para adicionar os nomes de arquivos em cada data, execute o seguinte:

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

A saída seria a seguinte:

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

Infelizmente, não tenho certeza de como impedir a quebra de linha e manter o nome do arquivo anexado ao final da data sem adicionar mais linhas ao script.


PS - Eu uso #!/usr/bin/env bashcomo usuário Python por dia e tenho versões diferentes do bashinstaladas no meu sistema em vez de#!/bin/bash

Danijel-James W
fonte
Caso você não tenha descoberto a parte de quebra de linha, o sinalizador -e está disponível para o programa de eco. Exemplo de uso poderia ser: echo -e "$(stat -f %Sm -t %Y%m%d_%H%M%S $AFile)\t$AFile.". No seu caso, poderia ser: echo -e "$(stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$i")\t$i." `
Thoth
14

O melhor é

date -r filename +"%Y-%m-%d %H:%M:%S"
rishi
fonte
Esta resposta é uma duplicata do stackoverflow.com/a/20807343/6320039
Ulysse BN
@UlysseBN não, é um pouco diferente. Ele está defendendo um melhor formato de data.
iconoclast
6

Adicionando à resposta @StevePenny, você pode querer cortar a parte não tão legível por humanos:

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

Eu queria obter a data de modificação do arquivo em YYYYMMDDHHMMSSformato. Aqui está como eu fiz isso:

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

Explicação.É a combinação destes 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
fonte
2

EDITADO: Acontece que eu esqueci as aspas necessárias para $entryimprimir corretamente e não dar o erro "não existe esse arquivo ou diretório". Muito obrigado a todos por me ajudarem!

Aqui está o meu 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

Imprime assim:

/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
fonte
2

Para as quebras de linha, editei seu código para obter algo sem quebras de linha.

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

Se o nome do arquivo não tiver espaços:

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

Isso é impresso como o seguinte formato:

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

Se os nomes de arquivos tiverem espaço (você também pode usar o seguinte comando para nomes de arquivos sem espaços, apenas parece complicado / feio que o anterior):

 ls -l <dir> | awk '{printf ("%s %s %s ",  $6,  $7, $8); for (i=9;   i<=NF; i++){ printf ("%s ", $i)}; printf ("\n")}'
Conta
fonte
Ah entendi! Isso funciona principalmente, exceto para os arquivos com os espaços nos nomes. Existe uma solução para isso?
Hokerie
Na verdade, tentei novamente e não funciona ... acontece que eu estava tentando um diretório que tinha nomes de arquivos sem espaços. = / Editado minha resposta abaixo
Hokerie
quando você diz que não funciona, pode dizer qual é o erro? funciona para mim quando eu o executei no meu sistema.
Bill
Eu recebi um "tal arquivo ou diretório".
Hokerie
Isso ocorre porque você passou um valor <dir>que não existe .... o código está perfeitamente correto.
Bill
0

Você pode usar:

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

Isso exibirá a data em 2 dígitos.

Se entre 1 e 9, ele adiciona o prefixo "0" e converte em 01 - 09.

Espero que isso atenda às expectativas.

Yoga Nathan
fonte