IDLメモ ファイル・ディレクトリ

パス操作

UNIX系OSとWindowsでは、ディレクトリの区切文字が異なるなど、パスの取扱いに異なる部分がある。移植性の高いプログラムを書くためにはパス操作をハードコーティングしないようにする。

環境固有の情報を得る (path_sep)

環境により異なる、ディレクトリ区切り文字(path delimiting character)、親ディレクトリ(parent directory)、検索パス(search path)のエントリの区切り文字をそれぞれ得る。

Result=path_sep() ; ディレクトリ区切り文字
Result=path_sep(/parent_directory) ; 親ディレクトリ
Result=path_sep(/search_path) ; 検索パスのエントリの区切り文字

完全修飾パスを作る (filepath, file_expand_path)

filepath 関数は与えられた基準パス(root_dir)、ファイル名(filename)、サブディレクトリ名(subdir1, subdir2)を組み合わせて完全修飾パス(fully-qualified path)を作る。作られたパスが実在するかどうかは関知しない。

Result=filepath('filename',root_dir='root_dir',subdirectory=['subdir1','subdir2'])

サブディレクトリ名は省略できる。

Result=filepath('filename',root_dir='root_dir')

ファイル名として長さ0の文字列を与えることでディレクトリ名が得られる。

Result=filepath('',root_dir='root_dir',subdirectory='subdir1')

file_expand_path 関数はカレントディレクトリを基準パスとして、ファイル名または相対パス(filename)から完全修飾パスを作る。この際、パスは正規化される(つまり結果に ../ は含まれない)。ワイルドカード(*など)を渡すことは好ましくない。

Result=file_expand_path('filename')

ファイルパスからディレクトリ名を抜き出す (file_dirname)

mark_directoryキーワードをつけると、末尾にディレクトリ区切り記号をつけてくれる。

Result=file_dirname('/path/to/file',/mark_directory)

ファイルパスからファイル名を抜き出す (file_basename)

もっとも右にあるディレクトリ区切り文字よりも後ろの文字列を返す。末尾のディレクトリ区切り文字は無視される。

Result=file_basename('/path/to/file')

拡張子も同時に除去できる。fold_case キーワードを指定すると大文字・小文字を区別しないので、Windows で便利。

Result=file_basename('path/to/file.pro','.pro')

コンパイル済のプロシージャまたは関数のパスを得る (routine_filepath, routine_info)

ROUTINE_FILEPATH関数(IDL 7.0以降で利用可能)はコンパイル済みのプロシージャまたは関数のパスを返す。またROUTINE_INFO関数はコンパイル済のプロシージャまたは関数に関する情報を提供する。IDL VMで実行した場合は、全てSAVEファイルのパスとなる。次の例では test というプロシージャ/関数の定義を含むファイル名を得ている。

; デフォルトではプロシージャのみが対象となる PRINT, ROUTINE_FILEPATH('test') ; /EITHER キーワードをつけると、関数のみが対象となる PRINT, ROUTINE_FILEPATH('test', /IS_FUNCTION) ; /EITHER キーワードをつけると、プロシージャ・関数の両方が対象となる PRINT, ROUTINE_FILEPATH('test', /EITHER) ; IDL6以前では次のようにする(プロシージャの場合) PRINT, (ROUTINE_INFO('test', /SOURCE)).(1) ; IDL6以前では次のようにする(関数の場合) PRINT, (ROUTINE_INFO('test', /SOURCE, /FUNCTIONS)).(1)

プログラムが存在するディレクトリ名を取得する。

PRINT, FILE_DIRNAME(ROUTINE_FILEPATH('test', /EITHER), /MARK_DIRECTORY)

IDL 8.2.2以降では、プロシージャ/関数名を省略した場合は、現在のルーチンが対象となる。つまり、自分自身がいまどこのパスに存在するのかがわかる。

PRINT, FILE_DIRNAME(ROUTINE_FILEPATH(/EITHER), /MARK_DIRECTORY)

testがコンパイルされていないときは、ROUTINE_FILEPATH関数は長さ0の文字列を返すので、testが呼び出し可能かどうかを判定できる。

IF ROUTINE_FILEPATH('test') eq '' THEN MESSAGE, 'test is not found'

2つのファイルパスが同じファイルを指すかどうかを判定する (file_same)

シンボリックリンク、ハードリンク、パス中の ../、環境変数や ~ (チルダ)の展開などにより、表記が異なる2つ以上のファイルパスが、同じファイルを指し示すことがある。file_same関数は、2つのファイルパスが同じファイルを指すかどうかを判定する。

Result=file_same(Path1, Path2)

ファイルパスPath1Path2が同じファイルを指しているとき結果は 1 (true)、そうでないとき 0 (false) となる。UNIXではi-nodeで比較が行われるのに対し、Windowsでは正規化したファイル名で比較が行われる。このため、Windowsではネットワーク上のファイルについて正しく評価できない場合がある。

file_search 関数は従来の findfile 関数の機能拡張版。

文法

Result=file_search(Path_Specification)

または再帰的な検索を行う場合

Result=file_search(Dir_Specification, Recur_Pattern)

引数

Path_Specification
マッチさせるパスを含む文字列(配列も可)。省略すると'*'が指定されたものとみなされる。
Dir_Specification
再帰的に検索するとき、起点となるディレクトリパスを含む文字列(配列も可)。省略するとカレントディレクトリのみを検索対象にする。
Recur_Pattern
マッチさせるファイル名を含む文字列。省略すると'*'が指定されたものとみなされる。

主なキーワード

count=variable
variableに見つかったファイルの数が入る。
expand_environment
非零にすると環境変数を展開する。0にすると展開を抑止する。expand_environmentの指定を省略した時、デフォルトでは、Unix では展開されるが、Windowsでは展開されない。
expand_tilde
非零にするとチルダ(~)をホームディレクトリに展開する。0にすると展開を抑止する。expand_tildeの指定を省略した時、デフォルトでは、Unix では展開されるが、Windowsでは展開されない。
fold_case
非零にすると大小文字を区別しない。0にすると大小文字を区別する。fold_caseの指定を省略した時、デフォルトでは、Unix では区別するが、Windowsでは区別しない。
fully_qualify_path
セットしたとき完全修飾パスを返す。
mark_directory
セットしたとき、マッチしたものがディレクトリであったとき、末尾にディレクトリ区切り記号を付加する。
match_initial_dot
セットしたとき、ドット(.)から始まるファイル名にもマッチするようになる。カレントディレクトリと親ディレクトリにはマッチしない。
nosort
セットしたとき、結果をソートしないで返す。Unix 環境で大量のファイルがマッチしたとき速くなる。
quote
セットしたとき、ワイルドカードの前にバックスラッシュをつけてエスケープできるようになる。
test_*
セットしたとき、ある条件に一致したファイルのみを返す。test_directory (ディレクトリ)、test_executable (実行可能)、test_read (読み込み可)、test_regular (通常のファイル)、test_write (書き込み可)、test_zero_length (長さ0) などがある。他に UNIX のみで利用可能なキーワードとして、sticky bit、special file、シンボリックリンクなどを判別するキーワードも存在する

ワイルドカード

*
任意の文字列 (長さ0の文字列を含む)。
?
任意の1文字。
[...]
文字クラス。[ ]の中に置かれた文字のいずれかにマッチする。[abc]とすると、a, b, c のいずれかにマッチする。[a-d]は[abcd]と等価。[ の直後に ! または ^ を置くと否定の意味になる。[^abc]とすると、a, b, c 以外の文字にマッチする。
{str, str, ...}
選択。いずれかの文字列にマッチする。
~
~user
ホームディレクトリで置換される(expand_tilde キーワードを参照)。~user の形式は Unix でのみサポートされる。
$var
${var}
環境変数varで置換される(expand_environment キーワードを参照)。後ろに通常の文字列が続く場合、${var}を使うことで変数名の範囲を指定する。
${var:-alttext}
環境変数 varが存在し、かつ長さ0でない場合、varで置換する。そうでなければ代替文字列 (alttext) で置換する。
${var-alttext}
環境変数 varが存在する場合(長さ0でも)varで置換する。そうでなければ代替文字列 (alttext) で置換する。

検索パスからファイルを検索 (file_which)

デフォルトでは !path から検索する。

Result=file_which('file_which.pro')

検索パス(search path)を指定することもできる。検索パスとは、path_sep(/search_path) が返す文字 (すなわち、Unix では :、Windowsでは ;)で区切られたディレクトリのリストである。

Result=file_which(getenv('PATH'), 'ls')

ファイルが存在するか、または特定の属性を持つかを調べる (file_test)

file_test関数は、ファイルの存在や属性を、ファイルを開くことなしに調べる。類似の機能を持つ関数としては、file_info (ファイルの状態を調べる)、file_search (パターンにマッチするファイルを検索する)、fstat (開いているファイルの状態を調べる) がある。

Result=file_test(File)

file_test関数は指定されたファイルFileが存在し、かつキーワードで指定された全ての属性にマッチするとき 1 (true) 、そうでなければ 0 (false) を返す。File は配列で複数のファイルを指定することも可能で、このとき戻り値も同じ要素数の配列となる。

主なキーワードとしては、directory (Fileがディレクトリであるとき 1 を返す; 以下同様)、executable (実行可能)、read (読み込み可)、regular (通常のファイル)、write(書き込み可)、zero_length (長さ0; ディレクトリに関してはシステム依存) などがある。他に UNIX のみで利用可能なキーワードとして、sticky bit、special file、シンボリックリンクなどを判別するキーワードも存在する。

Result=file_test(File, get_mode=variable)

get_mode キーワードを用いると、ファイルのパーミッションが8進数でvariableに格納される。結果はchmod (2)が返すものと同じである。

ファイルの状態を調べる (file_info)

file_info関数は、ファイルFileの状態を構造体で返す。複数のファイルを指定することも可能。類似の機能を持つ関数としては、file_test (ファイルが存在するか、または特定の属性を持つかを調べる)、fstat (開いているファイルの状態を調べる) がある。

Result=file_info(File)

戻り値Resultはフィールド数21の構造体であり、file_testで調べられる各属性を示すフラグの他、アクセス/作成/変更時刻やファイルサイズなども含まれる。

カレントディレクトリ

カレントディレクトリを変更 (cd)

環境によりデフォルトのカレントディレクトリが異なることに注意。また、引数を渡さないのと、長さ0の文字列を渡すのとでは動作が異なる。

cd,'path' ; カレントディレクトリを 'path' に移動。絶対パス、相対パスのどちらでも構わない
cd,'' ; カレントディレクトリをホームディレクトリ (Unix) または !DIR (Windows) に移動
cd ; なにもしない

currentキーワードを使うと、変更前のカレントディレクトリを保存できる。末尾のディレクトリ区切り記号はつかないことに注意。

cd,'path',current=olddir ; カレントディレクトリを 'path' に移動し、変更前のカレントディレクトリをolddirに保存する
cd,current=olddir ; カレントディレクトリをolddirに保存する

ディレクトリスタック操作 (pushd, popd, printd)

カレントディレクトリを 'path' に移動し、変更前のカレントディレクトリをディレクトリスタックに積む。

pushd,'path'

ディレクトリスタックの一番上からディレクトリを下ろし、カレントディレクトリとする。

popd

ディレクトリスタックの内容を表示する。

printd

ファイル・ディレクトリ操作

ファイルを開いての操作については、入出力編を参照。

ディレクトリを作成する (file_mkdir)

作成しようとするディレクトリの親ディレクトリが存在しない場合、親ディレクトリも再帰的に作成される (Unix の mkdir -p と似た動作)。また、既に存在するディレクトリを指定してもエラーにはならない。

file_mkdir,'newdir'
file_mkdir,'newdir1','newdir2' ; 複数のディレクトリを一度に作ることも可能

ファイル・ディレクトリを削除する (file_delete)

recursive キーワードをつけない場合、ファイルと空のディレクトリを削除できる。

file_delete,'file'

recursive キーワードをつけると、ディレクトリが空でなくても再帰的に削除する。引数を変数で指定する場合、変な値が入っていると悲惨なことになるので注意。

file_delete,'file',/recursive ;

Windows では recycle キーワードをつけると、ファイルを削除するかわりにゴミ箱に移動する(IDL 8.4以降)。

ファイル・ディレクトリのコピー・移動・名前変更 (file_copy, file_move)

file_copy プロシージャはファイルまたはディレクトリのコピーを行う。/ovserwriteキーワードをセットすると、コピー先のファイルが存在していても上書きする。既に開いているファイルのコピーを行うときは copy_lun プロシージャを用いる。

file_copy,SourcePath,DestPath

SourcePath
コピー元のファイルまたはディレクトリ。文字列配列で複数のコピー元を指定することも可能。ワイルドカードも利用可能。
DestPath
コピー先のファイルまたはディレクトリ。文字列配列で複数のコピー先を指定することも可能。

SourcePathDestPathがともに配列の時、SourcePath[0]DestPath[0]にコピーされるというように、DestPathの対応する要素が示すコピー先にコピーが行われる。当然両者の要素数は等しくなければならない。SourcePathが配列でDestPathがスカラーのとき、DestPathは既存のディレクトリでなければならない。このときコピー元のファイルはそのディレクトリの中にコピーされる。SourcePathでワイルドカードを指定したときも、DestPathは既存のディレクトリでなければならない。

recursiveキーワードをセットすると、ディレクトリをその階層構造を保ったままコピーすることができる。

file_copy,SourcePath,DestPath,/recursive

file_move プロシージャはファイルまたはディレクトリの移動・名前変更を行う。SourcePathDestPath の指定のルールはfile_copyと同様。/ovserwriteキーワードをセットすると、コピー先のファイルが存在していても上書きする。

file_move,SourcePath,DestPath

file_link はハードリンクやシンボリックリンクを作成する。SourcePathDestPath の指定のルールはfile_copyと同様。

file_link,SourcePath,DestPath ; シンボリックリンクを作成
file_link,SourcePath,DestPath,/hardlink ; ハードリンクを作成

file_readlink はシンボリックリンクPathの指す先を返す。

Result=file_readlink(Path)

/allow_nonexistent
存在しないPathを指定したときにエラーとならずヌル文字列を返す。
/allow_nonsymlink
Pathがシンボリックリンクでないときエラーとならずヌル文字列を返す。

パーミッションの変更 (file_chmod)

file_chmod はファイルのパーミッションを設定する。現在のパーミッションの得るにはfile_test関数get_mode キーワードを用いる。Windows では、execute, setuid, setgid, and sticky bits が存在しないため、これらのbitsを設定しても無視される。またWindowsでは 3 permission classes も存在しない。

ファイルFileのパーミッションを8進数Modeで指定する場合は次のようにする。Modechmod (2)で用いられるのと同じ形式である。

file_chmod,File,Mode

ファイルFileのパーミッションをそれぞれ個別のキーワードで指定することもできる。キーワードを0以外に設定するとパーミッションを与え、0にするとパーミッションを奪う。

file_chmod,File,/a_execute,/a_read,/a_write,/g_execute,/g_read,/g_write,/o_execute,/o_read,/o_write,/u_execute,/u_read,/u_write,/setgid,/setuid,/sticky_bit

/a_execute
全ユーザー 実行 (/g_execute, /o_execute, /u_execute を同時に設定するのと等価)
/a_read
全ユーザー 読み取り
/a_write
全ユーザー 書き込み
/o_*
その他のユーザー
/g_*
グループのメンバー
/u_*
ファイルの所有者
/setgid
the setgid bit
/setuid
the setuid bit
/sticky_bit
the sticky bit

file_chmod,File,/g_write,o_execute=0,o_read=0 ; グループのメンバーの書き込みを許可し、その他のユーザーの読み込みと実行を不可にする

西田圭佑 (NISHIDA Keisuke)
nishida at kwasan.kyoto-u.ac.jp
$Id: path.html,v 1.5 2022/05/30 12:31:42 nishida Exp nishida $