Klasör zaman damgalarını özyinelemeli olarak en yeni dosyaya nasıl değiştirebilirim?


16

Herkes bu klasördeki dosyaların en son zaman damgasını dayalı özyinelemeli klasörlerin zaman damgalarını nasıl değiştireceğini bilmek merak ediyordum.

Yani mesela:

jon @ UbuntuPanther: / media / media / MP3s / Foo Fighters / (1997-05-20) Renk ve Şekil $ ls -alF
toplam 55220
drwxr-xr-x 2 jon jon 4096 2010-08-30 12:34 ./
drwxr-xr-x 11 jon jon 4096 2010-08-30 12:34 ../
-rw-r - r-- 1 jon jon 1694044 2010-04-18 00:51 Foo Savaşçıları - Doll.mp3
-rw-r - r-- 1 jon jon 3151170 2010-04-18 00:51 Foo Fighters - Yeterli Uzay.mp3
-rw-r - r-- 1 jon jon 5004289 2010-04-18 00:52 Foo Savaşçıları - Everlong.mp3
-rw-r - r-- 1 jon jon 5803125 2010-04-18 00:51 Foo Fighters - Şubat Yıldızları.mp3
-rw-r - r-- 1 jon jon 4994903 2010-04-18 00:51 Foo Fighters - Hey, Johnny Park! .mp3
-rw-r - r-- 1 jon jon 4649556 2010-04-18 00:52 Foo Fighters - Maymun Anahtarı.mp3
-rw-r - r-- 1 jon jon 5216923 2010-04-18 00:51 Foo Fighters - My Hero.mp3
-rw-r - r-- 1 jon jon 4294291 2010-04-18 00:52 Foo Fighters - Benim Zavallı Beyin.mp3
-rw-r - r-- 1 jon jon 6778011 2010-04-18 00:52 Foo Fighters - Yeni Yol Ana Sayfa.mp3
-rw-r - r-- 1 jon jon 2956287 2010-04-18 00:51 Foo Savaşçıları - See You.mp3
-rw-r - r-- 1 jon jon 2730072 2010-04-18 00:51 Foo Fighters - Up in Arms.mp3
-rw-r - r-- 1 jon jon 6086821 2010-04-18 00:51 Foo Savaşçıları - Walking After You.mp3
-rw-r - r-- 1 jon jon 3033660 2010-04-18 00:52 Foo Fighters - Wind Up.mp3

"(1997-05-20) Renk ve Şekil" klasöründe zaman damgası 2010-04-18 00:52 olarak ayarlanacaktır.

Yanıtlar:


21

touch -rGeçerli saat (veya touch --reference=FILE) yerine başka bir dosyanın zaman damgasını kullanmak için kullanabilirsiniz

İşte iki çözüm. Her çözümde, ilk komut dizinin değişiklik süresini hemen altındaki en yeni dosyanınkine değiştirir ve ikinci komut tüm dizin ağacını özyinelemeli olarak inceler. cd '.../(1997-05-20) The Colour and The Shape'Komutlardan herhangi birini çalıştırmadan önce dizine ( ) geçin .

Zsh ( Dnokta dosyalarını yoksaymak için kaldırın ):

touch -r *(Dom[1]) .
touch -r **/*(Dom[1]) .

Linux'ta (veya daha genel olarak GNU find ile):

touch -r "$(find -mindepth 1 -maxdepth 1 -printf '%T+=%p\n' |
            sort |tail -n 1 | cut -d= -f2-)" .
touch -r "$(find -mindepth 1 -printf '%T+=%p\n' |
            sort |tail -n 1 | cut -d= -f2-)" .

Ancak bu adların dosya adlarında yeni satır karakteri almadığını unutmayın.


Komutlar işe yarıyor (Linux olanlarını kullandım) ama yinelemeli çalışmıyor. Kök klasörümde (/ media / media / MP3s) çalıştırdım ve oradaki sanatçı dizinlerinin geri kalanında böyle bir şans yok. Şimdiye kadar yardımlarınız için teşekkür ederim.
MonkeyWrench32

@ MonkeyWrench32: Sorunuzu anladığım gibi cevapladım. Komutu altındaki her dizine uygulamak istiyor musunuz /media/media/MP3s? Sonra zsh içinde: for d in /media/media/MP3s/**/*(/); do touch -r $d/*(Dom[1]) $d; done. Zsh olmadan (ama gerçekten zsh kullanın, sadece daha basittir): komutu bir komut dosyasına koyun ve çalıştırın find /media/media/MP3s -type d -execdir /path/to/the/script \;.
Gilles 'SO- kötü olmayı kes

Mükemmellik! Siz bir zsh ustasısınız! : D
MonkeyWrench32

Eğer kullanırsanız for d in ...o da klasörlerle çalışma, boşluk içerecek şekilde nasıl aşağıdakileri uyum sağlayabilir? (bu hala benim
çözümümde

@ rubo77 Neden bahsettiğinizi anlamıyorum. Gönderdiğim tüm çözümler boşluk içeren dosya adları üzerinde çalışıyor (bazıları yeni satır içeren dosya adlarında başarısız oluyor). Bazı çözümlerimin değişken ikameler etrafında çift tırnak gerektirmeyen zsh gerektirdiğini unutmayın.
Gilles 'SO- kötü olmayı kes'

3

Bu "özyinelemeli" değil, sadece bir klasördeki tüm zaman damgalarını değiştiriyor. Demek istediğin buysa, iki adım var.

stat -c '%Y' filenameçıkış damgası olacak filenameve stat -c '%Y %n' *irade çıktı klasöründe her dosyanın zaman damgası ve dosya adını, bu mevcut klasörde en son değiştirilen dosyasının dosya adını bulacaksınız böylece:

mostrecent="`stat -c '%Y %n' * | sort -n | tail -n1 | cut -d ' ' -f '2-'`"

İkinci düşüncede, klasördeki en yüksek zaman damgasını almanın daha kolay bir yolu var :

mostrecent="`ls -t | head -n1`"

Ardından, klasördeki tüm dosyaları bu dosyayla aynı zaman damgasına sahip olacak şekilde değiştirmek istersiniz. aynı değiştirilmiş zaman damgasına sahip touch -r foo barolacak şekilde değişecektir bar; foobu, klasördeki tüm dosyaları, en son değiştirilen dosyayla aynı değiştirilmiş zaman damgasına sahip olacak şekilde değiştirir:

touch -r "$mostrecent" *

Yani, tek astar:

touch -r "`ls -t | head -n1`" *

Ls çıkışını ayrıştırma kötü bir fikirdir , ancak cazip bir durum olduğunu kabul ediyorum. lsASCII olmayan karakterler içeren dosya adlarını karıştırırsa yine de risklidir . Tek gömlek istiyorsanız, zsh kullanın :-)
Gilles 'SO- kötü olmayı bırakın'

@Gilles Öyle, ama bunu yaparken bir sorunla karşılaşmadım; Sanırım dosya adlarım ASCII olmayan karakterler içermiyor. Cevabınız daha iyi olsa da
Michael Mrozek

2

İşi bir araya getirdim ve şimdi:

Bu, içindeki tüm dizinleri /tmp/test/her dizindeki en yeni dosyanın zaman damgasına değiştiren bir komut dosyası olacaktır :

#!/bin/bash
if [ -z "$1" ] ; then
  echo 'ERROR: Parameter missing. specify the folder!'
  exit
fi
#MODE=tail # change to newest file
MODE=head # change to oldest file
for d in "$1"/*/; do
  echo "running on $d"
  find "$d" -type d -execdir \
    echo touch --reference="$(find "$d" -mindepth 1 -maxdepth 1 -printf '%T+=%p\n' \
                              | sort | "$MODE" -n 1 | cut -d= -f2-)" "$d" \;
    # remove echo to really run it
done

/ tmp dosyasına şu şekilde bazı test dosyaları ekleyebilirsiniz:

mkdir /tmp/test
cd /tmp/test
mkdir d1
mkdir d2
touch d1/text1.txt
sleep 1
touch d1/movie1.mov
touch d2/movie2.mov
sleep 1
touch d2/text2.txt
touch notthis.file


1
düzenleme için teşekkürler, işe yarıyor! yankı "tekrar kaldırsa da , önce eksik gibi görünüyor, ama işe yarıyor.
rubo77

2

sadece kullan

find . -exec touch {} \;

0

Bu komut dosyasını, klasör zaman damgalarını en son içeriğe yinelemeli olarak ayarlamak için kullanın. (Gilles'in cevabına çok benziyor):

#! /bin/bash

# Change mtime of directories to that of latest file (or dir) under it, recursively
# Empty leaf directories, or dirs with only symlinks get the $default_timestamp

default_timestamp='1980-01-01 00:00:00'

dir="$1"

[ -d "$dir" ] || { echo "Usage: $0 directory" >&2; exit 1; }

find "$dir" -depth -type d | while read d; do
    latest=$(find "$d" -mindepth 1 -maxdepth 1 \( -type f -o -type d \) -printf '%T@ %p\n' | sort -n | tail -1 | cut -d' ' -f2-)
    if [ -n "$latest" ]; then
        touch -c -m -r "$latest" "$d" \
            || echo "ERROR setting mtime of '$d' using ref='$f'" >&2
    else
        touch -c -m -d "$default_timestamp" "$d" \
            || echo "ERROR setting mtime of '$d' to default '$default_timestamp'" >&2
    fi
done

0

@Gilles zsh komutunu aldım ve alt klasörlerde çalışmak için geliştirdim, ancak zsh'ın ** / * (FDod) kısmı için çok yetersiz olduğu görülüyor.

# Don't do this
for d in **/*(FDod); do touch -r "$d"/*(Dom[1]) "$d"; done

Tırnak işaretleri boşluk ve sekme içeren dizin girişlerinin düzgün çalışmasına izin verir. FD, ile başlayanlar da dahil olmak üzere boş olmayan dizinleri bulmasını sağlar. Od, önce derinlikte arama yapar , böylece üst klasör zaman damgaları düzgün bir şekilde güncellenir.

Test yaparken, ** / * (FDod) için performans ve bellek ayak izinin delice olduğunu fark ettim (sadece 650k klasörler için 1.4GB'ın üzerinde) ve klasörlere dokunmadan önce her şeyi okudu. Bul / oku ile değiştirdikten sonra çok daha hızlı hale geldi, hafızayı yakmadı ve neredeyse hemen başladı.

#! /usr/bin/env zsh
# Do this instead
find "$@" -depth -type d ! -empty -print0 |while IFS= read -r -d ''; do
    touch -r "$REPLY"/*(Dom[1]) "$REPLY"
done

Bir komut dosyasında çalıştırmıyorsanız, "$ @" yerine onu çalıştırmak istediğiniz klasörlerle değiştirin.


-1

Kabuk komutlarının belirsizliğini gerçekten sevmedim ve çabucak python'da yaptım.

Tüm dizin mtimes'lerini, içerideki en yeni dışlanmayan dosya / dir mtime değerine özyineli olarak ayarlar.

import os
import sys

EXCLUDE_FILES = ['.DS_Store']
EXCLUDE_DIRS = ['.git', '.hg']

def inheritMTime(path):
    for root, dirs, files in os.walk(path, topdown=False, followlinks=False):
        currentMaxMtime = None
        for subpath in files:
            if subpath in EXCLUDE_FILES:
                print "ignore file", os.path.join(root, subpath)
                continue
            currentMaxMtime = max(currentMaxMtime, os.lstat(os.path.join(root, subpath)).st_mtime)
        for subpath in dirs:
            if subpath in EXCLUDE_DIRS:
                print "ignore dir", os.path.join(root, subpath)
                continue
            currentMaxMtime = max(currentMaxMtime, os.lstat(os.path.join(root, subpath)).st_mtime)
        if currentMaxMtime is not None:
            os.utime(root, (currentMaxMtime, currentMaxMtime))

if __name__ == "__main__":
    for dir in os.listdir(sys.argv[1]):
        if os.path.isdir(dir):
            current = os.path.join(sys.argv[1], dir)
            inheritMTime(current)
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.