파일 이름에서 날짜 이후 파일이 수정되었는지 테스트


11

내가 함께라는 이름의 파일이 YYYYMMDD파일 이름에 같은를

file-name-20151002.txt

파일이 2015-10-02 이후에 수정 되었는지 확인하고 싶습니다 .

노트:

  • 의 출력을 보면이 작업을 수행 할 수 ls있지만 출력을 구문 분석 ls하는 것은 나쁜 생각이라는 것을 알고 있습니다.
  • 특정 날짜 이후의 모든 파일 을 찾을 필요는 없으며 한 번에 하나의 특정 파일 을 테스트 하면됩니다.
  • 파일을 만든 후 같은 날짜에 파일이 수정되는 것에 대해 걱정하지 않습니다. 즉, 20151002이름이있는 이 파일이 2015 년 10 월 3 일 이후에 수정 되었는지 알고 싶습니다 .
  • 저는 MacOs 10.9.5에 있습니다.

이전에 OS를 포함하지 않은 것에 대한 사과.
피터 그릴

답변:


4

가능한 방법은 다음과 같습니다.

  • OSX stat:

    newer () {
    tstamp=${1:${#1}-12:8}
    mtime=$(stat -f "%Sm" -t "%Y%m%d" "$1")
    [[ ${mtime} -le ${tstamp} ]] && printf '%s\n' "$1 : NO: mtime is ${mtime}" || printf '%s\n' "$1 : YES: mtime is ${mtime}"
    }
  • GNU date:

    newer () {
    tstamp=${1:${#1}-12:8}
    mtime=$(date '+%Y%m%d' -r "$1")
    [[ ${mtime} -le ${tstamp} ]] && printf '%s\n' "$1 : NO: mtime is ${mtime}" || printf '%s\n' "$1 : YES: mtime is ${mtime}"
    }
  • zsh 뿐:

    zmodload zsh/stat
    newer () {
    tstamp=${1:${#1}-12:8}
    mtime=$(zstat -F '%Y%m%d' +mtime -- $1)
    [[ ${mtime} -le ${tstamp} ]] && printf '%s\n' "$1 : NO: mtime is ${mtime}" || printf '%s\n' "$1 : YES: mtime is ${mtime}"
    }

용법:

최신 파일

출력 예 :

file-name-20150909.txt : YES: mtime is 20151026

또는

file-name-20151126.txt : NO: mtime is 20151026

9

다음 스크립트는 명령 행에 지정된 모든 파일의 날짜를 확인합니다.

그것은의 GNU 버전을 필요로 sed, datestat

$ cat check-dates.sh 
#! /bin/bash

for f in "$@" ; do
  # get date portion of filename
  fdate=$(basename "$f" .txt | sed -re 's/^.*(2015)/\1/')

  # convert it to seconds since epoch + 1 day
  fsecs=$(echo $(date +%s -d "$fdate") + 86400 | bc )

  # get modified timestamp of file in secs since epoch
  ftimestamp=$(stat -c %Y "$f")

  [ "$ftimestamp" -gt "$fsecs" ] && echo "$f has been modified after $fdate"
done

$ ./check-dates.sh file-name-20151002.txt 
file-name-20151002.txt has been modified after 20151002
$ ls -l file-name-20151002.txt 
-rw-rw-r-- 1 cas cas 0 Oct 26 19:21 file-name-20151002.txt

온라인 매뉴얼 페이지를 올바르게 읽으면 테스트되지 않았지만 Mac (및 FreeBSD 등)에서 작동 해야하는 버전이 있습니다.

#! /bin/bash

for f in "$@" ; do
  # get date portion of filename
  fdate=$(basename "$f" .txt | sed -e 's/^.*\(2015\)/\1/')

  # convert it to seconds since epoch + 1 day
  fsecs=$(echo $(date -j -f %Y%m%d "$fdate" +%s) + 86400 | bc )

  # get modified timestamp of file in secs since epoch
  ftimestamp=$(stat -f %m "$f")

  [ "$ftimestamp" -gt "$fsecs" ] && echo "$f has been modified after $fdate"
done

더 나은 솔루션은 POSIX에 비해 4-5 확장이 필요하지 않은 솔루션입니다.
토마스 디키

2
그렇다면 자신의 버전을 자유롭게 작성하십시오. 내가 쓰고 싶은 것이 아니라 내가 쓰고 싶은 것을 쓴다. GNU 버전의 도구를 사용하는 것도 포함된다. IMO, GNU 사실상의 표준입니다. 그리고 리눅스가 아닌, GNU가 아닌 nixes에 비해 사용중인 리눅스 배포판의 상대적 수는 그것을 지원합니다.
cas

6
@cas : 토마스의 의견에 대한 답장. 당신의 해결책을 개선하기위한 제안 일뿐입니다 ... 현실에서, "가장 표준적인"스크립트를 얻는 것은 보너스 일뿐만 아니라 필요합니다 (또는 오히려 필수). 많은 곳에서 GNU 버전의 도구를 설치할 수 없습니다 (일부 시스템의 최신 bash 버전이 2.x이고 awk가 너무 오래되어 원래 버전과 매우 가까운 3 곳의 다른 곳을 알고 있습니다). 이 질문의 요구는 아마 "치명적"은 아니지만 다른 사람들도 종종 구하거나 사용하지는 않지만, 휴대용 솔루션을 갖는 것은 일반적으로 +
Olivier Dulac

나는 무엇입니까 sed: illegal option -- r맥 OS 10.9.5 함께.
피터 그릴

-rsed확장 정규식을 사용하도록 지시 하는 GNU 옵션입니다. 당신은 기본적인 예를 들어 확장보다는 정규 표현식 (사용하도록 나오지 스크립트를 바꿀 수 sed -e 's/^.*\(2015\)/\1/')는의 GNU 버전이 필요하기 때문에 아마도 실패 할 것이다 그러나 스크립트의 나머지 부분 datestat, 나는 맥들이 있지만 (표준으로 그들과 함께 올 생각하지 않는다 미리 컴파일 된 패키지로 Mac에서 사용 가능)
cas

4

bash 및 statand expr를 사용 하여 날짜를 숫자로 가져 와서 비교하십시오.

#!/bin/bash
for file
do  moddate=$(stat -f %m -t %F "$file") # MacOS stat
    moddate=${moddate//-/} # 20151026
    if filedate=$(expr "$file" : '.*-\([0-9]*\).txt')
    then  if [ $moddate -gt $filedate ]
          then echo "$file: modified $moddate"
          fi
    fi
done

이것은 이전의 Linux 관련 답변이었습니다.

#!/bin/bash
for file
do  moddate=$(stat -c %y "$file")
    moddate=${moddate%% *} # 2015-10-26
    moddate=${moddate//-/} # 20151026
    if [[ "$file" =~ ([0-9]{8}).txt$ ]]
    then  if [[ $moddate > ${BASH_REMATCH[1]} ]]
          then echo "$file: modified $moddate"
          fi
    fi
done

bash =~regexp 연산자는 파일 이름의 8 자리를 bash 배열 BASH_REMATCH로 캡처합니다. [[ ]]에서 문자열을 숫자로 비교하지만 문자열을 비교합니다 [ -gt ].


MacOS 10.9.5에는 -c옵션 이없는 것 같습니다 stat.
Peter Grill

내 잘못이야. 동등한 것 같습니다 stat -f %m -t %F "$file". 죄송합니다. 테스트 할 수 없습니다.
meuh

stat귀하의 의견 에 따라 변경으로, 모든 테스트 사례에 대해 결과가 실행되는 것처럼 보이지만 출력은 없습니다. 그러나 무엇을 "$file" =~ ([0-9]{8}).txt$하고 있습니까?
Peter Grill

.txt파일 이름 끝에서 8 자리 숫자를 찾습니다 . 괄호 ()는 8 자리 부분을 캡처하며에서 찾을 수 있습니다 ${BASH_REMATCH[1]}.
meuh

귀하의 bash는 나던 일 경우 if [[=~]]에는 기본을 시도 할 수 있습니다 if filedate=$(expr "$file" : '.*-\([0-9]*\).txt')다음 교체 ${BASH_REMATCH[1]}에 의해 $filedate.
meuh

4

당신은 이것을 할 수 있습니다 :

  • 년 / 월 / 일 값을 쉘 변수로 추출하십시오.
  • 임시 파일을 만듭니다
  • touch명령을 사용하여 (시간 / 분 / 초에 0 추가) 임시 파일의 수정 날짜를 설정하십시오.

귀하의 질문은에 관한 bash것이므로 Linux를 사용하고있을 것입니다. test리눅스에서 사용되는 프로그램 (의 일부 로 coreutils는 ) 타임 스탬프 비교 (확장명이 -nt-ot에서 찾을 수 없습니다) POSIX를test .

POSIX는 다음에 대한 이론적 근거에서 이에 대해 언급합니다 test.

새로 생성되거나 KornShell에서 추가로 생성 된 몇 가지 추가 기본 조건은 조건부 명령 ( [[]]) 의 일부로 초기 제안에 나타났습니다 . 및 f1-ef f2. sh 유틸리티의 히스토리 구현에 빌드 된 테스트 유틸리티에 포함되지 않았으므로 조건부 명령이 쉘에서 제거 될 때 테스트 유틸리티로 전달되지 않았습니다.

그 확장을 사용하면

  • 비교하려는 날짜로 다른 임시 파일을 작성하십시오.
  • 요청한 비교를 위해 -nt연산자를 사용하십시오 test.

다음은 예입니다. OP에 의한 설명은 플랫폼을 언급 했으므로 stat임시 파일의 대안으로 사용할 수 있습니다 ( OSXLinux 비교 ).

#!/bin/bash
# inspect each file...

with_tempfile() {
    echo "** with temporary file $name"
    test=$MYTEMP/$name
    touch -t $date $test
    [ $name -nt $test ] && echo "...newer"
}

# alternatively (and this is system-dependent)
with_stat() {
    echo "** with stat command $name"
    stat=$(stat -t "%Y%m%d%H%M" -f "%Sm" $name)
    [ $stat -gt $date ] && echo "...newer"
}

MYTEMP=$(mktemp -d /var/tmp/isnewer.XXXXXX)
trap "rm -rf $MYTEMP" EXIT
for name in file-name-[0-9][0-9]*.txt
do
    if [ -f "$name" ];
    then
            date=${name%%.txt}
            date=${date/file-name-}
            date=${date//-/}2359
            with_tempfile $name
            with_stat $name
    fi
done

임시 파일을 만들 때는 trap명령으로 간과 된 파일을 제거하는 것이 일반적 입니다.
Thomas Dickey

저는 MacOS 10.9.5에 있습니다.
피터 그릴

설명 주셔서 감사합니다. 임시 파일은 추가 확장에 의존하는 일부 가능한 접근법만큼 우아하지는 않지만 일관성을 위해 간단한 샘플 스크립트를 제공합니다.
토마스 디키

1

다른 zsh접근법 :

zmodload zsh/stat # best in ~/.zshrc or
zmodload -F zsh/stat +b:zstat # to avoid overriding an eventual
                              # system stat command.
setopt extendedglob # best in ~/.zshrc

ls -ld -- **/*[0-9](#c8)*(De@'zstat -F %Y%m%d -A m +mtime $REPLY &&
  [[ ${(SM)${REPLY:t}#[0-9](#c8)} != $m ]]'@)

이름에 타임 스탬프처럼 보이지만 마지막 수정 시간에 해당하지 않는 파일을보고합니다.

zsh글로브와 변수를 조작 할 수있는 수많은 연산자가 있습니다. 모든 작업을 신속하고 (일반적으로 안정적으로) 수행하는 것이 매우 편리하지만 모든 것을 처리하는 것은 매우 어렵고 일반적으로 쓰기 전용 코드 (불법 코드에 대한 완곡 함)를 생성합니다. 명령 프롬프트에서 단일 용도로 쓸 때 읽을 필요가 없습니다.)

빠른 실행 :

  • **/pattern(qualifier): glob 한정자가있는 재귀 glob.
  • [0-9](#c8)8 자리와 일치합니다. 즉의 zsh을의 extendedglob 동등한의 ksh{8}([0-9]).
  • D: 숨겨진 파일 포함
  • e@...@: eval glob 한정자가 일부 텍스트를 실행하여 파일을 추가로 한정합니다. 전달 된 파일 경로$REPLY
  • zstat...$m배열 에서 YYYYMMDD로 포맷 된 mtime을 검색하십시오 .
  • ${REPLY:t}다음으로 확장 t의 파일의 꼬리 (기본 이름).
  • ${(SM)something#pattern}. 무언가 에서 부품 일치 패턴 을 추출하십시오 . 그것들 ( S ubstring search)과 ( Matched to M atched 부분)을 parameter expansion flags 라고 합니다 .SM
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.