폴더 타임 스탬프를 최신 파일로 재귀 적으로 변경하려면 어떻게합니까?


15

폴더의 파일에서 발견 된 최신 타임 스탬프를 기반으로 폴더의 타임 스탬프를 재귀 적으로 변경하는 방법을 아는 사람이 있는지 궁금합니다.

예를 들어 :

jon @ UbuntuPanther : / media / media / MP3s / Foo Fighters / (1997-05-20) 색과 모양 $ ls -alF
총 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 Fighters-Doll.mp3
-rw-r--r-- 1 jon jon 3151170 2010-04-18 00:51 Foo Fighters-충분한 공간 .mp3
-rw-r--r-- 1 jon jon 5004289 2010-04-18 00:52 푸 파이터스-Everlong.mp3
-rw-r--r-- 1 jon jon 5803125 2010-04-18 00:51 Foo Fighters-February Stars.mp3
-rw-r--r-- 1 jon jon 4994903 2010-04-18 00:51 푸 파이터스-안녕, 조니 파크! mp3
-rw-r--r-- 1 jon jon 4649556 2010-04-18 00:52 푸 파이터스-원숭이 렌치 .mp3
-rw-r--r-- 1 jon jon 5216923 2010-04-18 00:51 푸 파이터즈-My Hero.mp3
-rw-r--r-- 1 jon jon 4294291 2010-04-18 00:52 푸 파이터즈-My Poor Brain.mp3
-rw-r--r-- 1 jon jon 6778011 2010-04-18 00:52 Foo Fighters-New Way Home.mp3
-rw-r--r-- 1 jon jon 2956287 2010-04-18 00:51 푸 파이터스-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 Fighters-Walking After You.mp3
-rw-r--r-- 1 jon jon 3033660 2010-04-18 00:52 푸 파이터즈-Wind Up.mp3

"(1997-05-20) 색상 및 모양"폴더의 타임 스탬프는 2010-04-18 00:52로 설정됩니다.

답변:


20

touch -r현재 시간 (또는 touch --reference=FILE) 대신 다른 파일의 타임 스탬프를 사용할 수 있습니다

여기 두 가지 해결책이 있습니다. 각 솔루션에서 첫 번째 명령은 디렉토리의 수정 시간을 그 아래에있는 최신 파일의 수정 시간으로 변경하고 두 번째 명령은 전체 디렉토리 트리를 재귀 적으로 찾습니다. cd '.../(1997-05-20) The Colour and The Shape'명령을 실행하기 전에 디렉토리 ( )로 변경하십시오 .

zsh에서 ( D점 파일을 무시 하려면 제거 ) :

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

Linux (또는보다 일반적으로 GNU find)에서 :

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-)" .

그러나 이러한 파일 이름에는 줄 바꿈 문자가 없다고 가정하십시오.


명령이 작동하지만 (Linux 명령을 사용했지만) 재귀 적으로 작동하지 않습니다. 루트 폴더 (/ media / media / MP3s)에서 실행했으며 나머지 아티스트 디렉토리와는 아무런 운이 없었습니다. 지금까지 도와 주셔서 감사합니다.
MonkeyWrench32

@ MonkeyWrench32 : 이해 한대로 질문에 답변했습니다. 아래의 모든 디렉토리에 명령을 적용 /media/media/MP3s하시겠습니까? 그런 다음 zsh에서 : for d in /media/media/MP3s/**/*(/); do touch -r $d/*(Dom[1]) $d; done. zsh가 없다면 (실제로 zsh를 사용하면 더 간단합니다) : 명령을 스크립트에 넣고 실행하십시오 find /media/media/MP3s -type d -execdir /path/to/the/script \;.
Gilles 'SO- 악마 그만'

완전! 당신은 zsh 마스터입니다! : D
MonkeyWrench3232

당신이 사용하는 경우 for d in ...그것은 또한 폴더와 작업, 공백을 포함 할 수 있도록하는 방법은 다음을 적용 할 수 있습니까? (내 솔루션에는 여전히 누락되어 있음)
rubo77

@ rubo77 나는 당신이 무슨 말을하는지 이해하지 못합니다. 내가 게시 한 모든 솔루션은 공백이 포함 된 파일 이름에서 작동합니다 (일부는 줄 바꿈이 포함 된 파일 이름에서 실패합니다). 내 솔루션 중 일부에는 zsh가 필요하므로 변수 대체에 큰 따옴표가 필요하지 않습니다.
Gilles 'SO- 악마 그만해'

3

그것은 "재귀 적으로"가 아니라 폴더의 모든 타임 스탬프를 변경하는 것입니다. 그것이 당신이 의미하는 것이라면, 두 단계가 있습니다.

stat -c '%Y' filename출력의 타임 스탬프를 의지 filename하고 stat -c '%Y %n' *의지 출력 폴더에있는 모든 파일의 타임 스탬프와 파일 이름을이 현재 폴더에서 가장 최근에 수정 된 파일의 파일 이름을 찾을 수 있도록 :

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

제 생각에, 거기에 방법을 폴더에서 가장 높은 타임 스탬프를 얻을 수있는 쉬운 방법을 :

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

그런 다음 폴더의 모든 파일을 해당 파일과 동일한 타임 스탬프를 갖도록 변경하려고합니다. 와 동일한 수정 된 타임 스탬프를 갖도록 touch -r foo bar변경 되므로 폴더의 모든 파일이 가장 최근에 수정 된 파일과 동일한 수정 된 타임 스탬프를 갖도록 변경됩니다.barfoo

touch -r "$mostrecent" *

따라서 하나의 라이너는 다음과 같습니다.

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

ls의 출력을 파싱하는 것은 좋지 않은 생각 이지만, 유혹적인 경우라고 인정합니다. lsASCII가 아닌 문자가 포함 된 파일 이름을 맹 글링하는 경우 여전히 위험합니다 . 당신은 한 - 라이너를 원하는 경우, 사용 zsh을 :-)
질 'SO-정지 존재 악마'

@Gilles 그것은 그렇다. 그러나 나는 아직 그것을하는 데 문제가있다. 내 파일 이름에 ASCII가 아닌 문자가 포함되어 있지 않다고 가정합니다. 답변은 더 낫습니다
Michael Mrozek

2

나는 그 일을한데 모았다.

이것은 내부의 모든 디렉토리 /tmp/test/를 각 디렉토리 내의 최신 파일의 타임 스탬프로 변경하는 스크립트입니다 .

#!/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에 테스트 파일을 추가 할 수 있습니다.

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
편집 해 주셔서 감사합니다. 작동합니다! 반향이 "다시 제거 되지만 누락 된 것처럼 보이지만 작동합니다.
rubo77


0

이 스크립트를 사용하여 폴더 타임 스탬프를 최신 콘텐츠로 재귀 적으로 설정합니다. (그것은 Gilles의 답변과 매우 유사합니다) :

#! /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 명령을 가져 와서 하위 폴더에서 작동하도록 향상 시켰지만 zsh는 ** / * (FDod) 부분에 대해 비효율적으로 보입니다.

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

따옴표를 사용하면 공백과 탭이 포함 된 디렉토리 항목이 올바르게 작동합니다. FD는로 시작하는 디렉토리를 포함하여 비어 있지 않은 디렉토리를 찾도록합니다. od는 깊이 우선 방식으로 검색 하므로 상위 폴더 타임 스탬프가 올바르게 업데이트됩니다.

테스트 할 때 ** / * (FDod)의 성능 및 메모리 공간이 미쳤으며 (650k 폴더의 경우 1.4GB 이상) 폴더를 터치하기 전에 전체 내용을 읽었습니다. 찾기 / 읽기로 교체 한 후에는 훨씬 빨라지고 메모리를 굽지 않았으며 거의 ​​즉시 시작되었습니다.

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

스크립트에서 실행하지 않는 경우 "$ @"를 실행하려는 폴더로 바꾸십시오.


-1

나는 쉘 명령의 모호함을 정말로 좋아하지 않았고 파이썬에서 빨리했다.

그것은 모든 디렉토리 mtimes를 재발송되지 않은 최신의 제외되지 않은 파일 / dir mtime으로 재귀 적으로 설정합니다.

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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.