Dosya adının sonunda tarih değiştirilmiş zaman damgası bulunan bir grup dosyayı yeniden adlandırmak ister misiniz?


14

Yani, diyelim ki, 20 Haziran 2012'de g.txt en son değiştirildiği g.txt gibi bir grup dosyaya sahip bir dizinim var.

Tüm dosyaları (g.txt gibi) 20 Haziran 2012'nin son değiştirilme tarihinin sonuna ekleyerek nasıl yeniden adlandırabilirim?

Yanıtlar:


13

Hızlı ve acımasız Bash tek satırlık güncel dizindeki tüm (globbed) dosyalarını yeniden adlandırmak filename.txtiçin filename.txt-20120620:

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

Girişimci bir Bash nerd, onu kırmak için bir kenar durum bulacak, eminim. :)

Açıkçası, bu, bir dosyanın zaten bir tarih gibi görünen bir şeye sahip olup olmadığını kontrol etmek gibi istenen şeyleri yapmaz.


2
+1, iyi görünüyor. mv için ilk argüman olarak '-' kullanarak biraz daha sağlam hale getirebilirsiniz. '-'
cas

5
Bu nasıl bir dateuygulama? Benim GNU dategirişini işlemek için görünmüyor.
manatwork

RHEL 6 üzerinde coreutils 8.4
jgoldschrafe

2
@jgoldschrafe, kodun sizin için düzgün çalıştığından emin misiniz? pastebin.com/nNYubf3A
manatwork

5
iyi yakalamak manatwork. GNU tarihim 8.13 de stdin'den okumayı desteklemiyor. "-R" - örneğin "tarih +% Y% m% d -r $ f" olan bir dosyanın mod zamanının kullanılmasını destekler, bu nedenle bu özel durumda stat bile gerekmez.
cas

18

İşte goldschrafe'ın tek astarlı bir versiyonu:

  • stat kullanmaz
  • GNU tarihinin önceki sürümleriyle çalışır
  • dosya adlarındaki boşluklarla doğru şekilde baş eder
  • ayrıca bir tire ile başlayan dosya adlarıyla da baş eder

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


1
Bunu yapmalısınız, date -r "$f" +%Y%m%dyoksa POSIXLY_CORRECTortamdaysa çalışmaz . Genellikle seçenekler diğer argümanlardan önce gelmelidir.
Stéphane Chazelas

Bu "doğru yanıt" olmalıdır
invalidusername

Tabii ki parantezlere ihtiyacınız yok "${f}".
G-Man

ama bunu önermiş olduğumuz tarihler gibi olacak mı? Örneğin "Ymd-dosyaadı"?
timebandit

2

Zorunlu zsh bir astar (isteğe bağlı bileşenlerin bir kerelik yüklenmesini saymaz):

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

Biz kullanmak statgelen yerleşiğini zsh/statmodülü ve zmvyeniden adlandırma dosyaları işlevi. Ve işte, varsa uzantıdan önceki tarihi yerleştiren bir ekstra.

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

1

Anladığım kadarıyla değişiklik tarihinin ne olduğunu önceden bilmiyoruz. Bu yüzden her dosyadan almamız, çıktıyı biçimlendirmemiz ve her dosyayı dosya adlarında değişiklik tarihini içerecek şekilde yeniden adlandırmamız gerekir.

Bu komut dosyasını "modif_date.sh" gibi bir şey olarak kaydedebilir ve yürütülebilir yapabilirsiniz. Argüman olarak hedef dizini çağırıyoruz:

modif_date.sh txt_collection

Burada "txt_collection", yeniden adlandırmak istediğimiz tüm dosyalara sahip olduğumuz dizinin adıdır.

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

1
stat (1) için man sayfasını okuyun, betiğinizi yaklaşık 3/4 oranında nasıl daraltabileceğinizi öğrenmek için ... yukarıdakilerin çoğu tekerleği yeniden icat ediyor. özellikle, 'stat -c% Y', bir çağın bu tarihten itibaren saniye cinsinden değişiklik süresini verecektir (1970-01-01 00:00:00). Bu daha sonra zaman damgasını gerektiği gibi biçimlendirmek için tarihe (1) giriş olarak kullanılabilir. Örnek için yukarıdaki jgoldschrafe cevabına bakınız.
cas

@CraigSanders Üstte bu komut dosyası, farklı bir statyardımcı programa sahip olan veya hiç olmayan Linux dışındaki işletim sistemleri altında çalışıyor .
Gilles 'SO- kötü olmayı bırak

Not çıktısını ayrıştırma lsgüvenilir değildir . Bazı unix varyantlarında, kullanıcı ve grup adları, tarih sütunlarının hizalamasını atacak boşluklar içerebilir.
Gilles 'SO- kötü olmayı bırak

@giles: true, ancak mantıklı olan herkes herhangi bir linux olmayan sisteme GNU coreutils (ve diğer tüm GNU araçlarını) kurar. Sadece iyi bir kullanıcı alanı araçları seti değil, aynı zamanda temeldeki çekirdeğe bakılmaksızın tutarlı bir set elde etmenin en kolay yolu.
cas

1
(Devamı) ... (5) Başka hata: herhangi bir tarih / saat tarafından görüntülenen varsayar ls olarak cari yıl içinde olmalıdır bir tarih ve bir seferde (yerine bir tarih ve bir yıl). Bu doğru değil. Son altı aydır; önceki yılda olabilecek (örneğin, 27-Eylül-2016 - 31-Aralık-2016 son altı ay içinde). (6) Greg'in Wiki'sini (@Gilles'ın belirttiği gibi) papağan etme riski altında, yeni satır (lar) ve boşluklar içeren dosya adları bunun başarısız olmasına neden olabilir. … (Devam ediyor)
G-Man, '

0

Cas'in tek-astarının (goldschrafe'in onelinerine dayanan) idempotence ile uzatılmış versiyonu ,

yani tarih saatli önek dosyalarına genişletildi ve bunu yalnızca tarih saat önekine sahip olmayanlar için yapıldı .

Use-case: dizine yeni dosyalar eklerseniz ve henüz bulunmayanlara tarih saati öneki eklemek istiyorsanız faydalıdır.

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

Dosyalarınızın zaman damgaları vidalanmış ve jpeg ise, köknarların bunları EXIF ​​verileriyle düzeltmesini isteyebilirsiniz: for f in *.jpg ; do jhead -ft "$f" ; donekaynak: unix.stackexchange.com/a/290755/9689
Grzegorz Wierzowiecki
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.