Go의 표준 라이브러리에는 파일이 존재하는지 여부를 확인하는 기능 (Python 's 등 os.path.exists
)이 없습니다. 그것을 하는 관용적 방법 은 무엇입니까 ?
Go의 표준 라이브러리에는 파일이 존재하는지 여부를 확인하는 기능 (Python 's 등 os.path.exists
)이 없습니다. 그것을 하는 관용적 방법 은 무엇입니까 ?
답변:
파일이 존재하지 않는지 확인하려면 Python과 같습니다 if not os.path.exists(filename)
.
if _, err := os.Stat("/path/to/whatever"); os.IsNotExist(err) {
// path/to/whatever does not exist
}
파일이 존재하는지 확인하려면 Python과 같습니다 if os.path.exists(filename)
.
편집 : 최근 댓글 당
if _, err := os.Stat("/path/to/whatever"); err == nil {
// path/to/whatever exists
} else if os.IsNotExist(err) {
// path/to/whatever does *not* exist
} else {
// Schrodinger: file may or may not exist. See err for details.
// Therefore, do *NOT* use !os.IsNotExist(err) to test for file existence
}
NOTEXIST
하는 경우, 예를 들어, /etc/bashrc
존재의이 /etc/bashrc/foobar
돌아갑니다ENOTDIR
!os.IsNotExist(err)
. 파일이 존재하지만 os.Stat
다른 이유로 실패 할 수 있습니다 (예 : 권한, 디스크 실패). err == nil
조건으로 사용하면 "파일이 없습니다"와 같은 오류가 잘못 분류됩니다.
의해 답변을 Caleb Spare gonuts mailing list에 게시했습니다 .
[...] 실제로는 자주 필요하지 않으며 [...] 사용
os.Stat
이 필요한 경우에 충분히 사용 하기 쉽습니다.[...] 예를 들어 파일을 열 경우 파일이 먼저 존재하는지 확인할 이유가 없습니다. 파일은 확인과 열기 사이에 사라질 수 있으며, 어쨌든
os.Open
오류 를 확인해야합니다 . 따라서os.IsNotExist(err)
파일을 열려고 시도한 후 호출 하고 존재하지 않는 파일을 처리합니다 (특별한 처리가 필요한 경우).[...] 당신은 전혀 존재하지 않는 경로를 확인할 필요가 없습니다.
os.MkdirAll
경로가 이미 존재하는지 여부에 관계없이 작동합니다. (또한 해당 호출에서 오류를 확인해야합니다.)을 사용하는 대신을
os.Create
사용해야합니다os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
. 이렇게하면 파일이 이미 있으면 오류가 발생합니다. 또한 이것은 존재 여부를 미리 확인하는 버전과 달리 파일을 만드는 다른 것과 경쟁 조건이 없습니다.
출처 : https://groups.google.com/forum/#!msg/golang-nuts/Ayx-BMNdMFo/4rL8FFHr8v4J
다음 예제 os.Stat()
와 os.IsNotExist()
같이 및 기능을 사용해야합니다 .
// Exists reports whether the named file or directory exists.
func Exists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
user11617 의 예제 가 올바르지 않습니다. 파일이 존재하지 않는 경우에도 파일이 존재한다고보고하지만 다른 종류의 오류가 발생했습니다.
서명은 Exists (string) (bool, error) 여야합니다. 그런 다음 호출 사이트가 더 나아지지 않습니다.
그가 작성한 코드는 다음과 같이 더 좋습니다.
func Exists(name string) bool {
_, err := os.Stat(name)
return !os.IsNotExist(err)
}
그러나 나는 이것을 대신 제안한다.
func Exists(name string) (bool, error) {
_, err := os.Stat(name)
if os.IsNotExist(err) {
return false, nil
}
return err != nil, err
}
err != nil
대신에 반환 err == nil
? 오류가 있으면 파일이 존재하지 않을 수 있습니까?
다른 답변이 놓친 것은 함수에 주어진 경로가 실제로 디렉토리 일 수 있다는 것입니다. 다음 함수는 경로가 실제로 파일인지 확인합니다.
func fileExists(filename string) bool {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}
지적해야 할 또 다른 사항 :이 코드는 fileExists 함수가 실행되는 동안 다른 스레드 또는 프로세스가 지정된 파일을 삭제하거나 작성하는 경쟁 조건으로 이어질 수 있습니다.
이 문제가 걱정되면 스레드에서 잠금을 사용하거나이 기능에 대한 액세스를 직렬화하거나 여러 응용 프로그램이 관련된 경우 프로세스 간 세마포를 사용하십시오. 다른 응용 프로그램이 통제 범위를 벗어나면 운이 좋지 않을 것입니다.
기능 예 :
func file_is_exists(f string) bool {
_, err := os.Stat(f)
if os.IsNotExist(err) {
return false
}
return err == nil
}
먼저 os
패키지 측면에서 제공하는 기능 golang
은 유틸리티가 아니라 오류 검사기라는 몇 가지 측면을 살펴 보겠습니다. 즉, 크로스 플랫폼에서 오류를 처리하기위한 래퍼 일뿐입니다.
따라서 기본적 os.Stat
으로이 함수가 오류를 제공하지 않으면 파일이 존재한다는 것을 의미하는 경우 어떤 종류의 오류인지 확인 해야하는 경우 여기 에이 두 함수 os.IsNotExist
와 의 사용 이옵니다 os.IsExist
.
이것은 Stat
파일 던지기 오류가 존재하지 않기 때문에 또는 파일이 존재하기 때문에 오류가 발생하는 것으로 이해 될 수 있으며 문제가 있습니다.
이 함수가 취하는 매개 변수는 유형 error
이지만 전달할 수는 nil
있지만 의미가 없습니다.
이것은 또한 IsExist is not same as !IsNotExist
두 가지 다른 방법 이라는 사실을 지적합니다 .
이제 주어진 파일이 있는지 알고 싶다면 가장 좋은 방법은 다음과 같습니다.
if _, err := os.Stat(path/to/file); !os.IsNotExist(err){
//TODO
}
다른 답변에서 언급했듯이와 다른 플래그를 사용하여 필요한 동작 / 오류를 구성 할 수 있습니다 os.OpenFile
. 실제로, os.Create
그렇게하는 것이 현명한 기본값입니다.
// Create creates or truncates the named file. If the file already exists,
// it is truncated. If the file does not exist, it is created with mode 0666
// (before umask). If successful, methods on the returned File can
// be used for I/O; the associated file descriptor has mode O_RDWR.
// If there is an error, it will be of type *PathError.
func Create(name string) (*File, error) {
return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
관심있는 동작을 얻으려면이 플래그를 직접 결합해야합니다.
// Flags to OpenFile wrapping those of the underlying system. Not all
// flags may be implemented on a given system.
const (
// Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
O_RDONLY int = syscall.O_RDONLY // open the file read-only.
O_WRONLY int = syscall.O_WRONLY // open the file write-only.
O_RDWR int = syscall.O_RDWR // open the file read-write.
// The remaining values may be or'ed in to control behavior.
O_APPEND int = syscall.O_APPEND // append data to the file when writing.
O_CREATE int = syscall.O_CREAT // create a new file if none exists.
O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist.
O_SYNC int = syscall.O_SYNC // open for synchronous I/O.
O_TRUNC int = syscall.O_TRUNC // truncate regular writable file when opened.
)
선택한 내용에 따라 다른 오류가 발생합니다.
다음은 쓰기 위해 파일을 열고 자하는 예입니다. 그러나 사용자가 정상이라고 말한 경우에만 기존 파일을 자릅니다.
var f *os.File
if truncateWhenExists {
// O_TRUNC - truncate regular writable file when opened.
if f, err = os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644); err != nil {
log.Fatalln("failed to force-open file, err:", err)
}
} else {
// O_EXCL - used with O_CREATE, file must not exist
if f, err = os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0644); err != nil {
log.Fatalln("failed to open file, err:", err)
}
}