디렉터리 타임스탬프를 가장 최근에 수정된 파일로 설정(재귀적으로)

디렉터리 타임스탬프를 가장 최근에 수정된 파일로 설정(재귀적으로)

포함된 파일의 수정 시간을 반영하도록 디렉터리 및 해당 디렉터리 내의 모든 하위 폴더의 타임스탬프를 어떻게 변경할 수 있습니까?

예를 들어 다음 디렉터리 구조를 사용합니다.

[Jan 9]  root
├── [Jan 3]  file1
├── [Jan 7]  file2
├── [Jan 6]  sub1
│   ├── [Jan 2]  file3
│   └── [Jan 1]  file4
└── [Jan  4] sub2
    └── [Jan 8]  file5

다음은 이 콘텐츠를 생성하는 한 줄의 코드입니다.

mkdir -p root/sub1 root/sub2 && touch -d '2018-01-08' root/sub2/file5 && touch -d '2018-01-04' root/sub2/ && touch -d '2018-01-01' root/sub1/file4 && touch -d '2018-01-02' root/sub1/file3 && touch -d '2018-01-06' root/sub1/ && touch -d '2018-01-07' root/file2 && touch -d '2018-01-03' root/file1 && touch -d '2018-01-09' root/

그것은 나열할 수 있다tree -D

세 디렉터리의 타임스탬프를 다음과 같이 변경하고 싶습니다.

[Jan 8]  root
├── [Jan 3]  file1
├── [Jan 7]  file2
├── [Jan 2]  sub1
│   ├── [Jan 2]  file3
│   └── [Jan 1]  file4
└── [Jan 8]  sub2
    └── [Jan 8]  file5

노트:

  • 디렉터리의 현재 타임스탬프는 완전히 무시되고 새 타임스탬프는 콘텐츠만을 기준으로 설정됩니다.
  • 타임스탬프는 상위 디렉터리의 여러 수준까지 표시됩니다.

내가 이렇게 하는 이유는 rsync를 사용하여 디렉토리를 복사하기 위해서입니다. 디렉토리는 git에 체크인되며 저장소가 체크아웃된 어느 곳에서나 rsyncd될 수 있습니다. rsync가 모든 곳에서 일관되고 멱등성을 갖도록 하려면 모든 항목의 타임스탬프와 권한이 알려져 있는지 확인해야 합니다. 이미 git에 커밋된 시간을 기준으로 파일의 타임스탬프를 설정하는 스크립트가 있습니다. 또한 모든 파일과 디렉터리의 권한을 알려진 상태로 설정하는 스크립트도 있습니다. 내가 가진 유일한 문제는 파일에서 상위 디렉터리로의 버블링 타임스탬프에 관한 것입니다.

디렉터리 내용의 타임스탬프를 기반으로 디렉터리 타임스탬프를 설정하기 위해 명령줄에서 실행할 수 있는 한 줄 또는 짧은 스크립트를 원합니다.

답변1

내가 간과하고 있는 것이 아니라면(이것을 광범위하게 테스트하지는 않았습니다):

find . -depth -type d -execdir \
    sh -c 'touch "$PWD/$0" -r "$PWD/$0/$( ls -t "$PWD/$0" | head -n 1 )"' \
    {} \;

할 수 있는 작업:

  • 모든 하위 디렉터리를 찾습니다.
  • 이름을 알아보세요
  • 를 사용하여 ls -t날짜/시간 역순으로 내용을 나열하고 첫 번째 항목을 가져옵니다.
  • touch최신 객체를 타임스탬프로 사용하여 디렉토리를 터치하는 경우

올바른 날짜/시간 "버블링"을 위해 이 -depth옵션을 사용하면 하위 디렉터리가 처리됩니다.앞으로현재 하위 디렉터리("깊이 우선"). 하위 디렉터리가 처리되고 해당 날짜/시간이 업데이트되면 현재 디렉터리가 처리됩니다(하위 디렉터리 중 하나의 타임스탬프를 상속할 수 있음).

답변2

Zsh를 사용할 수 있다면 다음과 같이 원하는 작업을 수행할 수 있는 것 같습니다.

$ mkdir -p x/y; touch x/y/a x/b; sleep .1; touch x/y/a; sleep .1; touch x/b
$ find -depth -type d -execdir zsh -c 'touch "$1" -r "$1"/*(om[1])' zsh {} \;

GNU find를 사용하여 출력이 ./x/b최신이고 해당 타임스탬프가 에서 복사되는지 ./x테스트 합니다 ..

$ find -printf "%TT %p\n"  | sort -n
15:16:24.0182222830 ./x/y
15:16:24.0182222830 ./x/y/a
15:16:24.1222150510 .
15:16:24.1222150510 ./x
15:16:24.1222150510 ./x/b

일반적으로 파일 이름에 공백/줄 바꿈 등이 있으면 타임스탬프로 최신 파일을 찾는 것이 약간 까다롭습니다. (바라보다배쉬 FAQ 099.) Zsh를 사용하면 꽤 쉽게 할 수 있지만 위의 팁은명령줄 인수에서 최근 수정된 파일을 참조할 수 있습니까?

-depthfind버블링이 실제로 작동하도록 하위 디렉터리가 상위 디렉터리보다 먼저 처리되도록 지시합니다 .

타임스탬프가 버블링되는 것으로 계산되어야 하기 때문에 실제로 디렉터리의 타임스탬프를 완전히 무시하는 것은 아닙니다. 파일이 포함된 디렉터리는 파일에서 타임스탬프를 가져오지만비어 있는디렉터리는 원래 타임스탬프를 유지하며 해당 타임스탬프가 표시됩니다. 이 문제를 해결할 가치가 있는지 잘 모르겠습니다.

답변3

Linux에서는 이것이 나에게 잘 작동합니다.

while IFS=$'\t' read -r -a REPLY; do
  echo touch -c -h -d@"${REPLY[0]}" "${REPLY[1]}"
  touch -c -h -d@"${REPLY[0]}" "${REPLY[1]}"
done < <(du "${1:-.}" --time-style=+%s --time | cut -f 2-)

관련 정보