누구든지 해당 폴더에있는 파일의 최신 타임 스탬프를 기반으로 폴더의 타임 스탬프를 재귀 적으로 변경하는 방법을 알고 있는지 궁금합니다.
예를 들면 다음과 같습니다.
jon @ UbuntuPanther :/media/media/MP3s/Foo Fighters/(1997-05-20) The Color and The Shape $ ls -alF total 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-Enough Space.mp3 -rw-r--r-- 1 jon jon 5004289 2010-04-18 00:52 Foo Fighters-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 Foo Fighters- Hey, Johnny Park! .mp3 -rw-r--r-- 1 jon jon 4649556 2010-04-18 00:52 Foo Fighters-Monkey Wrench.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-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 Foo Fighters-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 Foo Fighters-Wind Up.mp3
"(1997-05-20) The Color and The Shape"폴더의 타임 스탬프는 2010-04-18 00:52로 설정됩니다.
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-)" .
그러나 그 파일 이름에 개행 문자가 없다고 가정합니다.
그냥 사용
find . -exec touch {} \;
이는 "재귀 적으로"가 아니라 폴더의 모든 타임 스탬프를 변경하는 것입니다. 그것이 의미하는 바라면 두 단계가 있습니다.
stat -c '%Y' filename
는 filename
의 타임 스탬프를 출력하고 stat -c '%Y %n' *
는 폴더에있는 모든 파일의 타임 스탬프와 파일 이름을 출력하므로 가장 최근에 수정 된 파일의 파일 이름을 찾습니다. 현재 폴더에서 :
mostrecent="`stat -c '%Y %n' * | sort -n | tail -n1 | cut -d ' ' -f '2-'`"
다시 생각하면 폴더에서 가장 높은 타임 스탬프를 얻는 더 쉬운 방법 way 가 있습니다.
mostrecent="`ls -t | head -n1`"
그런 다음 해당 파일과 동일한 타임 스탬프를 갖도록 폴더의 모든 파일을 변경하려고합니다. touch -r foo bar
는 bar
에서 foo
와 동일한 수정 된 타임 스탬프를 갖도록 변경하므로 폴더의 모든 파일이 가장 최근에 수정 된 파일과 동일한 수정 된 타임 스탬프를 갖도록 변경됩니다. :
touch -r "$mostrecent" *
따라서 한 줄짜리는 다음과 같습니다.
touch -r "`ls -t | head -n1`" *
나는 함께 일을하고 지금 :
다음은 /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
@Gilles zsh 명령을 사용하여 하위 폴더에서 작동하도록 개선했지만 zsh가 **/* (FDod) 부분에 대해 매우 비효율적 인 것 같습니다.
# Don't do this
for d in **/*(FDod); do touch -r "$d"/*(Dom[1]) "$d"; done
따옴표를 사용하면 공백과 탭이 포함 된 디렉토리 항목이 올바르게 작동합니다. FD는.로 시작하는 디렉토리를 포함하여 비어 있지 않은 디렉토리를 찾도록합니다. od는 depth-first 방식으로 검색하므로 상위 폴더 타임 스탬프가 제대로 업데이트됩니다.
테스트 할 때 **/* (FDod)의 성능과 메모리 공간이 미쳤다는 것을 알았습니다 (단지 650k 폴더의 경우 1.4GB 이상). 폴더를 터치하기 전에 전체를 읽었습니다. 찾기/읽기로 교체 한 후 훨씬 빨라졌고 메모리를 태우지 않고 거의 곧바로 시작되었습니다.
#! /usr/bin/env zsh
# Do this instead
find "[email protected]" -depth -type d ! -empty -print0 |while IFS= read -r -d ''; do
touch -r "$REPLY"/*(Dom[1]) "$REPLY"
done
스크립트에서 실행하지 않는 경우 "$ @"를 실행할 폴더로 바꿉니다.
이 스크립트를 사용하여 폴더 타임 스탬프를 최신 콘텐츠로 재귀 적으로 설정합니다. (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 '%[email protected] %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