こんにちは。田原です。
「第13回 fileコマンドが拡張されているぞ!」のまとめで「残りは次回」って書いていたことをすっかり忘れてました。ごめんなさい。今回は前々回のfileコマンドの続きを解説します。fileコマンドはファイルのリード/ライト、ファイルのコピー等のファイル操作、パス変換が1つのコマンドに押し込められていますので、ちょっと注意です。
1.リード/ライト系
1-1. READとSTRING
READとSTRINGはどちらもファイルの内容を変数へ読み込みます。
前者は改行は改行のまま読み込みます。後者は改行で区切ってリストとして読み込みます。
イキナリサンプルです。
file(READ "file.txt" DATA) message(STATUS "DATA=${DATA}") message(STATUS "------------") file(STRINGS "file.txt" DATA) message(STATUS "DATA=${DATA}") message(STATUS "------------")
test1 test2
1-2. WRITEとAPPEND
そのまんまです。ファイルへ上書きとファイルへ追記です。(サンプルの都合でファイル・コピーも使ってますが、解説を後述しています。)
サンプルです。
file(WRITE "file1.txt" "write1\nwrite2\n") file(COPY "file1.txt" DESTINATION "backup") file(APPEND "file1.txt" "write3\nwrite4\n")
1-3. ファイルのハッシュ値計算(リード系に分類されています)
指定されたファイルのMD5やSHA1等のハッシュ値を計算します。
計算できるハッシュ値は、STRINGコマンドのハッシュと同じです。
サンプルです。
file(MD5 "file.txt" RESULT) message(STATUS "RESULT=${RESULT}") message(STATUS "------------") file(SHA1 "file.txt" RESULT) message(STATUS "RESULT=${RESULT}") message(STATUS "------------")
他のハッシュ計算も使い方は同じです。
1-4. TIMESTAMPとTOUCH
stringコマンドのTIMESTAMPは現在時刻を返却しましたが、fileコマンドのTIMESTAMPは普通に指定したファイルの更新日時を返却します。
makeを使っている時、たまにtouchコマンドを使うことがあります。このコマンドは指定したファイルの更新日時を現在時刻にします。要するに「ちょっと触ってみる」コマンドです。どんなときに使うかというと、特定のファイルを指定してコンパイルさせたいような時に一々エディタを立ち上げないで済むので便利です。(まぁ最近はエディタやIDEで上書き保存でやることの方が多いように感じます。)
そのコマンドと同様のものがTOUCHとTOUCH_NOCREATEです。
TOUCHは、指定ファイルが無い時、空のファイルが作られます。
TOUCH_NOCREATEは、読んで字のごとしです。指定ファイルが無い時にそのファイルは生成されず、単に無視されます。
サンプルです。
file(TOUCH "file2.txt") file(TIMESTAMP "file2.txt" RESULT) message(STATUS "RESULT=${RESULT}") message(STATUS "------------") file(TOUCH_NOCREATE "file3.txt") file(TIMESTAMP "file3.txt" RESULT) message(STATUS "RESULT=${RESULT}") message(STATUS "------------")
他にGET_RUNTIME_DEPENDENCIESが3.16で追加されているようです。またGENERATEというコマンドもありました。でも、ごめんなさい。ざっと見てみたのですが、よく意味が分かっていません。解説は見送ります。
2.ファイル操作系
前節で書いたCOPYのように、ファイルのコピーや削除、フォルダの作成等のファイル操作を行うコマンドもfileコマンドです。第13回 fileコマンドが拡張されているぞ!で解説したGLOB/GLOB_RECURSEもファイル操作系です。
自明なコマンドばかりなので表で簡単に示します。
名前 | 動作内容 |
---|---|
GLOB / GLOB_RECURSE | ファイル・リストの抽出です。詳しくは第13回を参照下さい |
RENAME | ファイル名変更です(一般的なlinuxコマンドのようなmv(move)はありません) |
REMOVE | ファイル削除です |
REMOVE_RECURSE | 再帰的にファイルを削除します。フォルダを削除する時に使います |
MAKE_DIRECTORY | フォルダを作ります |
COPY / INSTALL | 複数のファイルを指定したフォルダへコピーします。 注意事項があります!!フォルダ・ツリーは維持されません。 全てのファイルが指定フォルダ直下へコピーされます(昔かなりハマりました) INSTALLはCOPYとほぼ同じです |
SIZE | ファイルのバイト数を指定変数へ取り出します |
READ_SYMLINK | シンボリックリンクが参照する実ファイルのパスを指定変数へ取り出します |
CREATE_LINK | 指定ファイルのシンボリックリンクを作成します |
振る舞いが分かりにくいものについてのサンプルです。
file(REMOVE_RECURSE "destination") file(COPY "file.txt" "backup/file1.txt" DESTINATION "destination") file(GLOB_RECURSE FILE_LIST RELATIVE "${CMAKE_SOURCE_DIR}" "destination/*") message(STATUS "FILE_LIST=${FILE_LIST}") message(STATUS "------------")
3.パス変換
文字列を「パス」とみなして変換します。ファイルの実体とは無関係です。実体がなくてもパス変換されます。
名前 | 動作内容 |
---|---|
RELATIVE_PATH | 絶対パスを相対パスへ変換します。 |
TO_CMAKE_PATH | CMake形式のパスへ変換します。要するに区切り記号が ‘/’ です |
TO_NATIVE_PATH | 使っているOS形式のパスへ変換します |
比較的 良く使うコマンドのサンプルです。
file(RELATIVE_PATH RESULT "C:/dummy/" "C:/dummy/abc.txt") message(STATUS "RESULT=${RESULT}") message(STATUS "------------") file(RELATIVE_PATH RESULT "/dummy/" "/dummy/def.txt") message(STATUS "RESULT=${RESULT}") message(STATUS "------------") file(TO_NATIVE_PATH "C:/dummy/abc.txt" RESULT) message(STATUS "RESULT=${RESULT}") message(STATUS "------------") file(TO_NATIVE_PATH "/dummy/def.txt" RESULT) message(STATUS "RESULT=${RESULT}") message(STATUS "------------") file(TO_CMAKE_PATH "C:\\dummy\\abc.txt" RESULT) message(STATUS "RESULT=${RESULT}") message(STATUS "------------") file(TO_CMAKE_PATH "\\dummy\\abc.txt" RESULT) message(STATUS "RESULT=${RESULT}") message(STATUS "------------")
4.まとめ
fileコマンド、如何でしたか? 毛色が似ているけど多くのケースで異なる系統のコマンドが1つのコマンドに押し込められていますね。覚えやすいような覚えにくいような微妙な線です。
そして、実はfileコマンドの一部と被るような機能が CMake -E
コマンドでも提供されています。次回はそれらについて対比してみたいと思います。
年内は恐らく今回の投稿が最後と思います。ちょっと早いですが、みなさんも良いお年をお過ごし下さい。
あ~~、年賀状を用意しなければ...