POSIX sh에서 -nt / -ot 테스트 수행


11

내장 test[유틸리티는 쉘이 "POSIX 모드"로 실행되는 경우에도 대부분의 쉘에서 ( "보다 오래된 -nt") 및 -ot( "이전보다") 테스트를 수행합니다. 내가 액세스 할 수있는 시스템). 이 테스트는 두 파일의 수정 타임 스탬프를 비교하기위한 것입니다. 문서화 된 의미는 구현에 따라 약간 다르지만 (하나 또는 다른 파일이 존재하지 않는 경우 발생하는 것과 관련하여) POSIX 사양test 에는 포함되지 않습니다 . 유틸리티를 위해 .

test조건부 명령이 [KornShell] 쉘에서 제거 될 때 유틸리티 로 전달 되지 않았습니다 . 유틸리티의 test히스토리 구현에 내장 된 유틸리티 에 포함되지 않았기 때문 sh입니다.

/bin/sh셸 스크립트 에서 파일 사이의 수정 타임 스탬프를 비교 하고 다음과 같이 한 파일이 다른 파일보다 최신인지 여부에 따라 조치를 취 한다고 가정 합니다.

if [ "$sigfile"     -nt "$timestamp" ] ||
   [ "$sigfile.tmp" -nt "$timestamp" ]
then
    return
fi

... 내가 사용할 수있는 다른 유틸리티는 무엇 make입니까? (스크립트의 나머지 부분을 말하면 다루기 어려울 것입니다)? 아니면 아무도 "역사적 구현"에서 스크립트를 실행하지 sh않거나 다음 과 같은 특정 쉘에 대한 글을 사임 하지 않을 것이라고 가정해야 bash합니까?


내 대답에서 볼 수 있듯이 bash는 약 이후 예상되는 방식으로 -nt기능을 구현하지 않습니다 test. 1995. 올바른 행동을 원 find하더라도 기본 표현을 사용해야합니다 bash.
schily

답변:


10

가능하게 :

f1=/path/to/file_1
f2=/path/to/file_2

if [ -n "$(find -L "$f1" -prune -newer "$f2")" ]; then
    printf '%s is newer than %s\n' "$f1" "$f2"
fi

파일에 절대 경로를 사용하면 filename에 잘못된 긍정이 포함되어 줄 바꿈 만 포함됩니다.

상대 경로를 사용하는 경우 find명령을 다음으로 변경하십시오 .

find -L "$f1" -prune -newer "$f2" -exec echo . \;

기술적으로, 줄 $f1바꿈 만 포함 하면 실패한다고 생각합니다 .)
ilkkachu

1
@ilkkachu는 -exec echo x \;비슷한 작업을 할 수 있습니까?
muru

@muru, 예. -printf표준이라면 쉬울 것입니다
ilkkachu

3
@Kusalananda AFAICT의 find'종료 상태는 개별 테스트의 결과와 무관 find합니다. 실제로 테스트를 실행하는 데 오류가있는 경우를 제외하고는 find파일이없는 경우에도 0을 종료합니다.
muru

1
의 동작은 [ / -nt /nofile ]구현 에 따라 다르지만 오류는 출력하지 않습니다.
Stéphane Chazelas

7

가장 오래된 Unix 명령 중 하나를 사용하는 경우 일 수 있습니다 ls.

x=$(ls -tdL -- "$a" "$b")
[ "$x" = "$a
$b" ]

a가 b보다 최신이면 결과는 true입니다.


3
파일 이름이 -(missing --)으로 시작하면 작동하지 않습니다 . 이 ( -L가)와 같아야합니다 -nt. 즉 비교 작동하지 않습니다 x$'x\nx'예를 들면.
Stéphane Chazelas

1
에크! 또한 허.
Kusalananda

4

흥미로운 질문을 제기하고 먼저 확인해야하는 주장을했습니다.

나는 다음의 행동을 점검했다.

$shell -c '[ Makefile -nt SCCS/s.Makefile ] && echo newer'

다양한 껍질로. 결과는 다음과 같습니다.

  • bash 작동하지 않습니다-아무것도 인쇄하지 않습니다.

  • 보쉬 작품

  • 대시 가 작동하지 않습니다. 아무것도 인쇄하지 않습니다.

  • ksh88 작동하지 않음-아무것도 인쇄하지 않습니다.

  • ksh93 작품

  • mksh 작동하지 않음-아무것도 인쇄하지 않습니다.

  • posh prints : posh : [: -nt : 예기치 않은 연산자 / 오퍼랜드

  • 야쉬 작품

  • zsh 는 최신 버전에서 작동하며 이전 버전은 아무것도 인쇄하지 않습니다.

따라서 9 개의 쉘 중 4 개는 -nt 기능을 지원하고 올바르게 구현합니다. 이 경우 올바르게 의미 : 초 초 타임 스탬프 입도를 지원하는 최신 플랫폼에서 타임 스탬프를 비교할 수 있습니다. 내가 선택한 파일은 일반적으로 타임 스탬프에서 몇 마이크로 초 만 다릅니다.

작동하는 find구현 을 찾는 것이 더 쉽기 때문에 교체하는 것이 좋습니다.

if [ "$file1" -nt "$file2" ] ; then
    echo newer
fi

바이 find기반 표현.

if [ "$( find "$file1" -newer "$file2" )" ]; then
    echo newer
fi

적어도 $file1개행을 포함하지 않는 한 작동 합니다.

if [ "$( find -L "$file1" -newer "$file2" -exec echo newer \; )" ]; then
    echo newer
fi

조금 느리지 만 올바르게 작동합니다.

BTW : make와 관련하여 모든 make 구현에 대해 말할 수는 없지만 SunPro Make약 초 이후의 나노 초 단위 시간 비교를 지원합니다. 20 년 동안 smakegmake최근에이 기능을 추가했습니다.


1
"초 작동하지 않음"테스트가 초 단위 타임 스탬프 (확실히?) 또는 다른 것을 비교하지 못하여 작동하지 않습니까? 테스트와 관련된 파일의 실제 타임 스탬프는 무엇입니까? 테스트를 위해 +1!
Kusalananda

2
공감대는 아마도 대립적 표현에 관한 것이라고 생각합니다. 여기서 제한 (일부 상황에서는 중요)이라고 부르는 것이 더 공정합니다. findbusybox 또는 heirloom-toolchest와 같은 일부 구현에는 동일한 제한이 있습니다.
Stéphane Chazelas

3
당신은 필요 했어 -L하여에 대한 find버전에 해당하는 것으로 -nt. 또한 시작 파일 이름에 실패 -하거나 !, (...
스테판 Chazelas가

2
사실, 나는 대립적 표현을 사용할 때 종종 다운 보트를 얻는다. 답변 시작시 컨텍스트 (두 번째 해상도로 잘릴 때 동일한 타임 스탬프 내에서 수정 된 파일)를 언급하면 ​​도움이됩니다.
Stéphane Chazelas

1
@schily, 그렇습니다 .BSD findfind -f "$file"그것을 가지고 있지만 이식성이 없습니다.
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.