OS facilities — 운영체제 기능 활용하기
OS facilities — 운영체제 기능 활용하기
R은 단순한 통계 분석 도구를 넘어서, 그 아래에서 돌아가는 운영체제에 다가가는 기능도 꽤 많이 갖추고 있어요. 이 덕분에 R을 일종의 스크립트 언어처럼 쓸 수 있고, 실제로 R 자신이 패키지를 설치할 때 같은 일을 하고 있죠. 이 챕터에서는 파일과 디렉터리를 다루는 방법, 파일 경로를 이해하는 법, 시스템 명령을 실행하는 법, 그리고 압축·아카이브 파일을 읽고 쓰는 법을 하나씩 살펴볼게요.
출처: R 공식 매뉴얼
본문
R은 자기 자신이 실행되고 있는 운영체제에 접근하는 기능이 상당히 방대해요. 이 점 덕분에 R은 스크립팅 언어로도 쓰일 수 있고, 그 능력은 R 스스로도 자주 사용하죠 — 예를 들어 패키지를 설치할 때가 대표적이에요.
게다가 R 자신의 스크립트가 모든 플랫폼에서 똑같이 동작해야 하다 보니, 이 스크립팅 기능들을 가능한 한 플랫폼 독립적으로 만들기 위해 꽤 많은 노력이 들어갔어요.
14.1 파일과 디렉터리
파일과 디렉터리를 다루는 함수는 아주 많아요. 여기서는 그중에서도 자주 쓰이는 것들 위주로 짚어볼게요.
빈 파일이나 빈 디렉터리를 만들 때는 file.create나 dir.create를 써요. 이 둘은 POSIX의 touch와 mkdir 명령에 해당하는 함수예요. R 세션 디렉터리 안에 임시 파일·임시 디렉터리를 만들고 싶다면 tempfile을 살펴보면 돼요.
파일을 지울 때는 file.remove나 unlink를 쓸 수 있어요. unlink는 디렉터리 트리째로 지울 수 있다는 점이 조금 달라요.
디렉터리 안에 무엇이 있는지 목록을 볼 때는 list.files(별칭으로 dir도 있어요)나 list.dirs를 사용해요. 이 함수들은 정규 표현식으로 파일을 골라낼 수 있는데, 와일드카드로 고르고 싶다면 Sys.glob을 쓰면 돼요.
파일 경로에 대한 여러 정보(예를 들어 이건 파일인지 디렉터리인지 같은 것)는 file.info로 알아낼 수 있어요.
파일이 '있는지'를 확인하는 방법도 여러 가지가 있어요. 파일이 파일시스템에는 존재하더라도 지금 사용자에게는 보이지 않을 수도 있거든요. file.exists, file.access, file_test라는 함수들이 각각 조금씩 다른 방식으로 이 테스트를 제공해요. 그중 file_test는 셸 스크립트에 익숙한 사람을 위한 POSIX test 명령의 R 버전이라고 보면 돼요.
file.copy는 POSIX의 cp 명령에 해당하는 R 함수예요.
파일을 고르는 작업은 file.choose로 대화형으로 할 수 있어요. Windows 포트에서는 좀 더 다재다능한 choose.files와 choose.dir이 있고, tcltk 패키지에도 비슷한 함수들이 있어요 — tk_choose.files와 tk_choose.dir이죠.
file.show와 file.edit는 파일 하나 또는 여러 개를 R 포트에 맞는 방식으로 보여주거나 편집해 주는 함수예요. 콘솔(Windows의 RGui라거나 macOS의 R.app 같은 것)이 사용 중이면 그 콘솔의 기능을 이용해요.
파일시스템의 링크(symlink 같은)를 다루는 지원도 조금 있는데, file.link와 Sys.readlink를 살펴보면 돼요.
14.2 파일 경로(Filepaths)
몇 가지 예외를 빼면, R은 파일 경로를 다루는 일을 기본적으로 바탕이 되는 운영체제 함수에 맡겨요. 그래서 이 부분은 운영체제에 따라 달라질 수 있고, 실제로도 달라져요 — 운영체제의 버전 수준까지도요. 운영체제가 파일 경로를 어떻게 해석해야 하는지에 대한 POSIX 표준이 있는데, 많은 R 사용자가 POSIX 준수를 당연하게 여겨요. 하지만 Windows는 준수를 주장하지 않고, 다른 운영체제들도 완전히 준수하지 않을 수 있어요.
파일 경로와 관련해서 실제로 부딪혀 본 문제들을 몇 가지 정리하면 이래요.
-
POSIX 파일시스템은 대소문자를 구분해요. 그래서
foo.png와Foo.PNG는 서로 다른 파일이에요. 하지만 Windows와 macOS의 기본값은 대소문자를 구분하지 않고, 이동식 저장장치에 흔히 쓰이는 FAT 파일시스템도 보통 대소문자를 구분하지 않아요(모든 경로가 소문자로 매핑될 수도 있어요). -
Windows의 거의 모든 OS 서비스는 경로 구분자로 슬래시(
/)든 백슬래시든 지원해요. R은 알려진 예외들을 Windows가 요구하는 형태로 변환해 주죠. -
끝에 슬래시가 붙는 경로(예:
foo/)의 동작은 운영체제에 따라 달라요. 이런 경로는 Windows에서 유효하지 않으니 동작을 기대하면 안 돼요. POSIX-2008은 이런 경로가 디렉터리만 매칭하도록 요구하지만, 더 이른 버전은 파일까지 매칭하는 걸 허용했어요. 그래서 되도록 쓰지 않는 게 좋아요. -
/abc//def처럼 슬래시가 여러 개 연속으로 오는 경로는 POSIX 파일시스템에서 유효하고 슬래시 하나인 것처럼 취급돼요. Windows의 OS 함수도 보통은 받아들여요. 다만 맨 앞에 오는 이중 슬래시는 다른 의미를 가질 수 있으니 주의하세요. -
Windows의 UNC 경로(예:
\\server\dir1\dir2\file이나\\?\UNC\server\dir1\dir2\file)는 지원되지 않지만, 일부 R 함수에서는 동작할 수 있어요. POSIX 파일시스템은 맨 앞의 이중 슬래시를 특별하게 취급해도 된다고 허용돼 있어요. -
Windows는 드라이브 문자를 포함하고 드라이브 안의 현재 디렉터리에 상대적인 경로도 허용해요. 예를 들어 드라이브
d:의 현재 디렉터리가/a/b/c라면d:foo/bar는d:/a/b/c/foo/bar를 가리켜요. 이런 경로가 동작하도록 의도되어 있지만, 절대 경로를 쓰는 쪽이 더 안전해요.
basename과 dirname은 파일 경로의 일부를 골라내는 함수예요. 경로를 여러 구성 요소로부터 조립할 때 권장하는 방법은 file.path예요. 그리고 pathexpand는 '틸드 확장(tilde expansion)'을 해 줘요 — 홈 디렉터리(현재 사용자, 어쩌면 다른 사용자의 것까지)를 값으로 치환해 주죠.
링크가 있는 파일시스템에서는 하나의 파일을 여러 경로로 가리킬 수 있어요. 이때 normalizePath가 정식(canonical) 경로를 찾아줘요.
Windows에는 짧은(8.3) 파일 이름과 긴 파일 이름이라는 개념이 있어요. normalizePath는 긴 이름을 쓴 절대 경로를 돌려주고, shortPathName은 짧은 이름 버전을 돌려줘요. 후자는 공백을 포함하지 않고 구분자로 백슬래시를 쓰기 때문에, R에서 이름을 내보낼 때 유용할 때가 있어요.
파일 권한도 관련 있는 주제예요. R은 소유자/그룹/모두에 대한 읽기/쓰기/실행 권한이라는 POSIX 개념을 지원하지만, 파일시스템에 따라 일부만 지원될 수 있어요. 예를 들어 Windows에서는 R 세션을 돌리는 계정 기준으로 읽기 전용 파일만 인식돼요. 접근 제어 목록(ACL)은 여러 파일시스템에서 쓰이지만, 합의된 표준이 없어서 R은 이를 제어할 방법이 없어요. 권한을 바꾸고 싶다면 Sys.chmod를 쓰세요.
14.3 시스템 명령(System commands)
system과 system2 함수는 시스템 명령을 실행하고 선택적으로 그 출력을 모아오는 데 쓰여요. system2는 조금 더 일반적이지만, 무엇보다 크로스 플랫폼 코드를 작성하기 쉽다는 장점이 있어요.
system은 Windows에서 다른 운영체제와 다르게 동작해요(같은 이름의 C API 호출이 그렇게 동작하기 때문이에요). 다른 곳에서는 명령을 실행하기 위해 셸을 호출하지만, Windows 포트의 R에는 그 역할을 하는 shell 함수가 따로 있어요.
운영체제에 어떤 명령이 있는지 알아보려면 Sys.which를 써요. 이 함수는 크로스 플랫폼 방식으로 그걸 시도해 주는데, 아쉽게도 표준 OS 서비스가 아니라서 완벽하진 않아요.
shQuote는 현재 운영체제의 명령에서 필요할 때 파일 경로를 따옴표로 감싸 주는 함수예요.
14.4 압축과 아카이브(Compression and Archives)
최근 버전의 R은 압축 파일을 — 대개는 투명하게 — 읽고 쓸 수 있는 기능이 상당히 방대해요. R에서 파일을 읽는 일은 대부분 연결(connection)을 통해 이뤄지는데, 파일(또는 URL)에 연결을 여는 데 쓰는 file 함수는 파일의 '매직(magic)' 헤더에서 사용된 압축 종류를 알아내 골라 잡아요.
가장 오래 전부터 지원됐던 압축 방식은 gzip이고, 여전히 좋은 일반적인 절충안이에요. 예전 Unix compress 유틸리티로 압축된 파일도 읽을 수 있지만, 그런 파일은 점점 드물어지고 있어요. bzip2와 xz라는 두 가지 다른 압축 방식도 사용할 수 있어요. 이 둘은 보통 더 높은 압축률(파일에 따라 훨씬 높은)을 얻는 대신, 압축 해제가 느리고 압축은 훨씬 느려요.
xz와 lzma 압축은 서로 혼동되기 쉬운데(https://en.wikipedia.org/wiki/Xz와 https://en.wikipedia.org/wiki/LZMA를 참고하세요), R은 둘 중 대부분의 버전으로 압축된 파일을 읽을 수 있어요.
파일 아카이브는 여러 파일을 한데 모아 놓은 단일 파일이에요. 가장 흔한 건 R 패키지를 배포할 때 쓰는 'tarball'과 zip 파일이죠. R은 둘 다 목록을 볼 수도 풀 수도 있는데(untar와 unzip 함수 참고), 만들 수도 있어요(zip의 경우 외부 프로그램의 도움을 받아서요).
더 알아보기
- 이 챕터에서 다룬 함수들의 전체 목록과 세부 동작은 R 도움말(
?file.create,?system,?normalizePath등)에서 확인할 수 있어요. - 운영체제 자체와 더 깊이 상호작용하고 싶다면 「R Installation and Administration」 매뉴얼의 관련 절을 함께 보면 도움이 돼요.
- 연결(connection)과 관련된 더 넓은 이야기, 즉 데이터를 읽고 쓸 때 연결이 어떻게 동작하는지는 「R Data Import/Export」 매뉴얼에서 다뤄져요.