에
[ -f "$file" ]
이 [
명령은 저장된 경로에서 stat()
(아님 lstat()
) 시스템 호출을 수행하고 해당 시스템 호출이 성공하고 파일 형식 이 " regular " 인 경우 true를$file
리턴 합니다 .stat()
따라서 [ -f "$file" ]
true를 반환하면 파일이 존재하고 일반 파일 또는 결국 일반 파일로 해석되는 심볼릭 링크라고 말할 수 있습니다 stat()
.
그러나 false를 반환 [ ! -f "$file" ]
하거나 ! [ -f "$file" ]
true 또는 true를 반환 하면 여러 가지 가능성이 있습니다.
- 파일이 존재하지 않습니다
- 파일이 존재하지만 일반 파일 이 아닙니다 (장치, fifo, 디렉토리, 소켓 등일 수 있음).
- 파일이 존재하지만 상위 디렉토리에 대한 검색 권한이 없습니다
- 파일이 존재하지만 액세스 할 수있는 경로가 너무 깁니다
- 파일은 일반 파일에 대한 심볼릭 링크이지만 심볼릭 링크를 해결하는 데 관련된 일부 디렉토리에 대한 검색 권한이 없습니다.
- ...
stat()
시스템 호출이 실패 할 수 있는 다른 이유 .
간단히 말해 다음과 같아야합니다.
if [ -f "$file" ]; then
printf '"%s" is a path to a regular file or symlink to regular file\n' "$file"
elif [ -e "$file" ]; then
printf '"%s" exists but is not a regular file\n' "$file"
elif [ -L "$file" ]; then
printf '"%s" exists, is a symlink but I cannot tell if it eventually resolves to an actual file, regular or not\n' "$file"
else
printf 'I cannot tell if "%s" exists, let alone whether it is a regular file or not\n' "$file"
fi
파일이 존재하지 않음을 확인하려면 stat()
오류 코드와 함께 리턴 하는 시스템 호출이 필요합니다 ENOENT
( ENOTDIR
경로 구성 요소 중 하나가 디렉토리가 아닌 경로임을 알려줍니다. 해당 경로로 존재합니다). 불행히도 [
명령은 우리에게 그것을 알려주지 않습니다. 오류 코드가 ENOENT, EACCESS (권한이 거부 됨), ENAMETOOLONG 또는 다른 어떤 것이 든 거짓을 리턴합니다.
[ -e "$file" ]
테스트도 수행 할 수 있습니다 ls -Ld -- "$file" > /dev/null
. 이 경우 정보를 프로그래밍 방식으로 쉽게 사용할 수 없지만 실패한 ls
이유를 알려줍니다 stat()
.
$ file=/var/spool/cron/crontabs/root
$ if [ ! -e "$file" ]; then echo does not exist; fi
does not exist
$ if ! ls -Ld -- "$file" > /dev/null; then echo stat failed; fi
ls: cannot access '/var/spool/cron/crontabs/root': Permission denied
stat failed
적어도 ls
파일이 존재하지 않기 때문에 파일이 존재하지 않기 때문에 그렇지 않다고 말합니다. 파일의 존재 여부를 알 수 없기 때문입니다. [
명령은 문제를 무시했다.
zsh
셸을 사용하면 $ERRNO
실패한 [
명령 다음에 특수 변수를 사용하여 오류 코드를 쿼리 $errnos
하고 zsh/system
모듈 의 특수 배열을 사용하여 해당 번호를 디코딩 할 수 있습니다 .
zmodload zsh/system
ERRNO=0
if [ ! -f "$file" ]; then
err=$ERRNO
case $errnos[err] in
("") echo exists, not a regular file;;
(ENOENT|ENOTDIR)
if [ -L "$file" ]; then
echo broken link
else
echo does not exist
fi;;
(*) syserror -p "can't tell: " "$err"
esac
fi
(의 최신 버전으로 빌드 할 때 $errnos
일부 버전zsh
gcc
에서는 지원이 중단되었습니다 ).