저는 보편적인 편집/번역 시스템을 만들고 있습니다. 파일이 컴파일/변환되었는지 확인하는 한 가지 방법은 소스 파일과 대상 파일의 수정 날짜를 비교하는 것입니다.
이 작업을 수행하려면 bash 스크립트를 작성해야 합니다.
source_file=foo;
target_file=bar;
stat_source=$(stat source_file);
stat_target=$(stat target_file);
그런데 통계 출력에서 날짜를 추출하고 비교하려면 어떻게 해야 합니까? stat
파일이 마지막으로 수정된 시기를 비교하는 것보다 더 좋은 방법이 있습니까 ?
로그 파일에서 stat를 호출하면 다음과 같은 결과가 나타납니다.
16777220 12391188 -rw-r--r-- 1 alexamil staff 0 321 "Jun 22 17:45:53 2017" "Jun 22 17:20:51 2017" "Jun 22 17:20:51 2017" "Jun 22 15:40:19 2017" 4096 8 0 test.log
AFAICT, 시간 단위는 초 이상입니다. 가능하다면 이보다 더 세분화된 것을 얻어야 합니다.
답변1
사용하고 있다는 점을 고려하면stat
test
(비슷한 기능이지만 BSD와 GNU의 출력 형식은 다릅니다.) 직접 비교를 수행하는 이 유틸리티를 사용할 수도 있습니다 .
FILE1 -nt FILE2
FILE1 is newer (modification date) than FILE2
FILE1 -ot FILE2
FILE1 is older than FILE2
귀하의 예에서는
if [ "$source_file" -nt "$target_file" ]
then
printf '%s\n' "$source_file is newer than $target_file"
fi
이 기능은 POSIX에서는 사용할 수 없습니다(해당 내용 참조).선적 서류 비치test
), 그 이유는 다음과 같습니다.
새로 발명되었거나 KornShell에서 나온 일부 추가 기본 명령은 조건부 명령([[]])의 일부로 초기 제안에 나타났습니다. s1
>
s2, s1<
s2, str = 패턴, str != 패턴, f1-nt
f2, f1-ot
f2 및 f1 -ef f2. 조건부 명령이 셸에서 제거되면 sh 유틸리티의 기록 구현에 내장된 테스트 유틸리티에 아직 포함되지 않았기 때문에 테스트 유틸리티로 전송되지 않습니다.
그러나 이는 향후 변경될 수 있습니다.이 기능이 널리 지원되기 때문입니다.
피연산자가 심볼릭 링크인 경우 심볼릭 링크 대상의 수정 시간이 고려된다는 점에 유의하세요(일반적으로 원하는 것이니 find -newer
그렇지 않은 경우 사용하세요). 심볼릭 링크를 확인할 수 없을 때 구현 간 동작(일부는 기존 파일이 항상 확인되지 않은 파일보다 최신이라고 생각하고 일부는 항상 보고함)잘못된구문 분석할 수 없는 피연산자가 있는 경우).
또한 모든 구현이 1초 미만의 세분성을 지원하는 것은 아닙니다(예: 버전 4.4 기준으로 bash
's test
/ 내장 기능은 여전히 지원하지 않지만 GNU 및/또는 ' 내장 기능은 적어도 GNU/Linux에서는 지원합니다).[
test
test
zsh
ksh93
참고로:
답변2
이 Linux 시스템에서 테스트되었습니다. 파일 시간을 테스트하는 일반적인 방법은 셸을 사용하는 것입니다.
[ file1 -nt file2 ] && echo "yes"
몇 초 안에 완료될 수 있을 것 같습니다. 이렇게 하면 1초 미만의 시간 차이가 있는 파일에 영향을 미치며 차이가 감지되지 않습니다.
$ touch file2; sleep 0.1; touch file1; [ file1 -nt file2 ] && echo "yes"
문제를 확인하려면(점 뒤의 시간은 나노초 단위임):
$ ls --time-style=full-iso -l file?
-rw-r--r-- 1 user user 0 2017-06-23 01:37:01.707387495 -0400 file1
-rw-r--r-- 1 user user 0 2017-06-23 01:37:01.599392538 -0400 file2
file1
보다 약간 최신입니다 file2
.
이제 문제는 시간 값을 올바르게 처리하는 방법입니다.
한 가지 해결책은 ls의 형식화된 출력을 사용하는 것입니다.
$ ls --time-style=+%s.%N -l file?
-rw-r--r-- 1 user user 0 1498196221.707387495 file1
-rw-r--r-- 1 user user 0 1498196221.599392538 file2
시간을 두 개의 변수로 추출합니다(점 없이).
$ file1time=$(ls --time-style=+%s%N -l file1 | awk "{print(\$6)}")
$ file2time=$(ls --time-style=+%s%N -l file2 | awk "{print(\$6)}")
그리고 시간을 비교하십시오(나노초 단위의 시간은 64비트 값에 거의 맞지 않습니다. 시스템이 64비트를 사용하지 않으면 이 비교는 실패합니다).
$ [ $file1time -gt $file2time ] && echo "yes"
yes
이는 file1
더 많다는 것을 보여준다.file2
ls
원하는 형식을 얻을 수 없다면 stat를 시도해 볼 수 있습니다 .
$ stat file1
File: file1
Size: 0 Blocks: 0 IO Block: 4096 regular file
Device: 805h/2053d Inode: 9180838 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ user) Gid: ( 1000/ user)
Access: 2017-06-23 01:37:01.707387495 -0400
Modify: 2017-06-23 01:37:01.707387495 -0400
Change: 2017-06-23 01:37:01.707387495 -0400
Birth: -
출력에 나노초가 표시되면 시간을 구문 분석하고 형식을 지정하려면 날짜가 필요합니다.
$ stat --printf='%y\n' file1
2017-06-23 01:37:01.707387495 -0400
$ date +'%s%N' -d "$(stat --printf='%y\n' file1)"
1498196221707387495
다른 모든 것은 동일합니다. file1과 file2의 결과를 두 변수에 할당하고 수치 비교를 수행합니다.
답변3
내장되지 않은 Linux를 사용하려는 경우 test
GNU coreutils의 일부인 외부 명령을 사용할 수 있습니다. ( test
대부분의 쉘에 대한 또 다른 이름 [
이며 내장되어 있습니다). 나노초 단위(최대 파일 시스템 보고 정확도)를 갖습니다.
/usr/bin/test "$target" -nt "$source"
이 연산자는 POSIX에서 정의되지 않지만 dash, bash, pdksh, mksh, ATT ksh, zsh, GNU coreutils 및 BusyBox를 -nt
포함한 많은 구현에 존재합니다 . test
그러나 많은 구현(dash, bash, pdksh, mksh, BusyBox - Debian jessie에서 테스트됨)은 1초 단위만 지원합니다.
그러나 작업을 위해 특별히 설계된 도구를 사용하는 것이 더 나은 생각일 것입니다.만들다. 특정 파일이 다른 파일보다 최신일 때만 명령을 실행하는 것이 make의 전부입니다. 이름이 지정된 파일에 다음을 포함합니다 Makefile
(각 명령줄 앞에 탭이 필요합니다).
target: source
echo This command is only executed if target is newer than source
do_stuff <source >$@
make target
이를 생성한 명령을 실행하려면 실행하세요 . target
존재하고 보다 최신인 경우 source
명령이 실행되지 않습니다. 자세한 내용은 make의 문서 중 일부를 읽어보세요.
답변4
POSIXly에서는 다음을 사용합니다 find
.
if find "$source_file" -prune -newer "$target_file" | grep -q '^'; then
printf '%s\n' "$source_file is newer than $target_file"
else
echo "It's not newer or one of the files is not accessible"
fi
심볼릭 링크의 경우 심볼릭 링크 자체의 실행 시간을 비교합니다. 심볼릭 링크의 대상을 비교하려면 -H
또는 -L
옵션을 추가하세요.
이 가정은 술어 중 하나로 $source_file
시작하지도 -
않고 해당 하지도 않습니다. find
임의의 파일 이름을 처리해야 하는 경우 먼저 다음을 수행해야 합니다.
case $source_file in
(["-+()!"]*) source_file=./$source_file;;
esac
GNU 및 FreeBSD find
구현은 최소한 1초 미만의 세분성을 지원합니다. AFAICT, macos는 HFS+ 파일 시스템의 파일 속성에 최소한 1초 미만의 정보를 저장하지 않는 것 같습니다.