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

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

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"

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


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


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

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)

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

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

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")}'

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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.