Renomeando um monte de arquivos com data e hora modificadas no final do nome do arquivo?

14

Então, digamos, eu tenho um diretório com um monte de arquivos como g.txt, onde o g.txt foi modificado pela última vez, digamos, em 20 de junho de 2012.

Como eu renomearia em lote todos os arquivos (como g.txt) com a data da última modificação de 20 de junho de 2012 anexada no final?

    
por InquilineKea 18.07.2012 / 03:56

5 respostas

13

Uma linha de Bash rápida e suja para renomear todos os arquivos (globbed) no diretório atual de filename.txt para filename.txt-20120620 :

for f in *; do mv -- "$f" "$f-$(stat -c %Y "$f" | date +%Y%m%d)"; done

Um nerd Bash empreendedor vai encontrar algum argumento para quebrá-lo, tenho certeza. :)

Obviamente, isso não faz coisas desejáveis, como verificar se um arquivo já tem algo parecido com uma data no final.

    
por 18.07.2012 / 04:36
17

aqui está uma versão do one-liner da goldschrafe que:

  • não usa estatística
  • funciona com versões anteriores da data do GNU
  • resolve corretamente os espaços nos nomes de arquivos
  • também lida com nomes de arquivos que começam com um traço

    for f in *; do mv -- "$f" "$f-$(date -r "$f" +%Y%m%d)"; done

por 20.07.2012 / 02:59
2

One-liner zsh obrigatório (sem contar o carregamento único de componentes opcionais):

zmodload zsh/stat
autoload -U zmv
zmv -n '(*)' '$1-$(stat -F %Y%m%d +mtime -- $1)'

Usamos o stat incorporado no zsh/stat module e a função zmv para renomear arquivos. E aqui está um extra que coloca a data antes da extensão, se houver.

zmv -n '(*)' '$1:r-$(stat -F %Y%m%d +mtime -- $1)${${1:e}:+.$1:e}'
    
por 19.07.2012 / 02:41
1

Como eu entendi, não sabemos de antemão qual é a data da modificação. Portanto, precisamos obtê-lo de cada arquivo, formatar a saída e renomear cada arquivo de forma que inclua a data de modificação nos nomes de arquivos.

Você pode salvar este script como algo como "modif_date.sh" e torná-lo executável. Nós o invocamos com o diretório de destino como o argumento:

modif_date.sh txt_collection

Onde "txt_collection" é o nome do diretório onde temos todos os arquivos que queremos renomear.

#!/bin/sh

# Override any locale setting to get known month names
export LC_ALL=c
# First we check for the argument
if [ -z "$1" ]; then
    echo "Usage: $0 directory"
    exit 1
fi

# Here we check if the argument is an absolute or relative path. It works both ways
case "${1}" in
  /*) work_dir=${1};;
  *) work_dir=${PWD}/${1};;
esac

# We need a for loop to treat file by file inside our target directory
for i in *; do
    # If the modification date is in the same year, "ls -l" shows us the timestamp.
    # So in this case we use our current year. 
    test_year='ls -Ggl "${work_dir}/${i}" | awk '{ print $6 }''
    case ${test_year} in *:*) 
        modif_year='date '+%Y''
        ;;
    *)
        modif_year=${test_year}
        ;;
    esac
    # The month output from "ls -l" is in short names. We convert it to numbers.
    name_month='ls -Ggl "${work_dir}/${i}" | awk '{ print $4 }''
    case ${name_month} in
            Jan) num_month=01 ;;
            Feb) num_month=02 ;;
        Mar) num_month=03 ;;
        Apr) num_month=04 ;;
        May) num_month=05 ;;
        Jun) num_month=06 ;;
        Jul) num_month=07 ;;
        Aug) num_month=08 ;;
        Sep) num_month=09 ;;
        Oct) num_month=10 ;;
        Nov) num_month=11 ;;
        Dec) num_month=12 ;;
        *) echo "ERROR!"; exit 1 ;;
    esac
    # Here is the date we will use for each file
    modif_date='ls -Ggl "${work_dir}/${i}" | awk '{ print $5 }''${num_month}${modif_year}
    # And finally, here we actually rename each file to include
    # the last modification date as part of the filename.
    mv "${work_dir}/${i}" "${work_dir}/${i}-${modif_date}"
done
    
por 18.07.2012 / 06:30
0

Aqui está a versão do one-liner do cas, (baseado no oneliner do goldschrafe) ampliado com idempotência ,

i.e. estendido para prefixar arquivos com data e hora e para fazer isso apenas para aqueles que ainda não têm data de prefixo .

Caso de uso: útil se você adicionar novos arquivos ao diretório e quiser adicionar prefixo de data aos que ainda não tiverem um.

for f in * ; do
  if [[ "$f" != ????-??-??' '??:??:??' - '* ]]; then
    mv -v -- "$f" "$(date -r "$f" +%Y-%m-%d' '%H:%M:%S) - $f" ;
  fi;
done
    
por 30.06.2018 / 16:02