File.CopyError 예외

File.CopyError 예외

파일이나 디렉터리를 복사하는 작업이 실패했을 때 발생하는 예외예요. 복사 대상이나 목적지가 제대로 준비되어 있지 않으면 이 예외가 떠요.

예를 들어 존재하지 않는 파일을 재귀적으로 복사하려고 하면 다음처럼 에러가 나요.

iex> File.cp_r!("non_existent", "source_dir/subdir")
** (File.CopyError) could not copy recursively from "non_existent" to "source_dir/subdir". non_existent: no such file or directory

출처: File.CopyError exception

본문

File.cp_r/3File.cp_r!/3처럼 재귀적으로 복사하는 함수는, 원본 파일이 존재하지 않거나 목적지 디렉터리가 없을 때 이 예외를 던져요. 이름에 느낌표가 붙은 버전(!)은 실패 시 예외를 던지고, 느낌표가 없는 버전은 {:ok, ...} / {:error, ... 튜플로 돌려주는 차이를 기억해 두면 좋아요.

이 예외는 문제를 분석하기 쉽도록 여러 공개 필드를 제공해요. 이 필드들은 자유롭게 접근해서 사용할 수 있어요.

  • :source (Path.t/0) — 복사하려는 원본 경로예요.
  • :destination (Path.t/0) — 복사가 도착해야 할 목적지 경로예요.
  • :reason (File.posix/0) — 파일을 복사하지 못한 이유예요.

에러를 받아서 어디에서 문제가 생겼는지, 왜 실패했는지를 로그로 남기거나 사용자에게 보여줄 때 이 필드들이 유용하게 쓰여요.

실무에서 이 예외를 마주하는 순간은 보통 두 가지예요. 한 가지는 원본 경로에 파일이 실제로 없는 경우이고, 다른 한 가지는 목적지 디렉터리가 만들어져 있지 않은 경우예요. 특히 재귀 복사(cp_r)는 여러 경로를 오가기 때문에, 어떤 경로가 어디까지 진행됐는지 추적하기가 쉽지 않아요. 그래서 이 예외가 던져지면 :source:destination 필드를 살펴 "원본이 없어서인지, 목적지가 없어서인지"를 먼저 좁혀 보는 게 좋아요. 경우에 따라 목적지 디렉터리를 미리 만들어 두면 해결될 때도 있어요.

복사 실패를 우아하게 처리하고 싶다면 느낌표가 없는 File.cp/3 계열을 써서 {:error, reason}을 받는 것도 방법이에요. 실패가 흔할 수 있는 상황이라면 예외에만 의존하기보다, 반환값으로 분기하는 방식이 더 다루기 편할 수 있어요.

더 알아보기

  • File.cp_r/3File.cp_r!/3의 차이(튜플 반환 vs 예외 발생)를 함께 확인해 보세요.
  • 원본 경로 해석에 대한 자세한 내용은 Path 모듈 문서를 참고해요.
  • 파일 작업 전반의 오류 구조를 이해하려면 File 모듈과 File.posix/0 타입을 함께 보면 좋아요.