読者です 読者をやめる 読者になる 読者になる

システムコールとシェルスクリプトを利用して、Fortranのコードから「ディレクトリがなければ作る」を実行

fortran programming

2016-02-28追記

変数を渡せるようにしたこっちの方が良い→
natures flyers: Fortran で call system() するときに変数 (variable) を渡す方法


古い記述

計算実行中のディレクトリが入力する設定ファイルやら出力されるデータやらセーブデータやらでごちゃごちゃしてる現状を改善したい。ディレクトリを幾つか作って整理できないか?というのが動機。入力はともかく、出力されるデータの入れ物(ディレクトリ)は F90 のプログラムが自分で作って欲しいところだが…

まずは
http://objectmix.com/fortran/741113-how-create-new-folder-fortran-77-a.html
を参考にしてみた。

  call system('mkdir save_data')

で ./save_data が作られた。call system() って便利だな。

program test_save
  implicit none
  integer :: hoge=777
  integer :: fuga=666
  real(8) :: vec(3) = (/-3.0d0, -2.0d0, -1.0d0/)
  character(len=72) :: restart_file
  
  CALL system('mkdir save_data')
  
  !! determine the file name
  write(restart_file,"('./save_data/restart001.save')")
  open(200,file=restart_file,status="replace",position="rewind",form="formatted")
    write(200,"(2(i9,1x))") hoge, fuga
    write(200,"(3(es20.13,1x))") vec(1:3)
  close(200)
  
  stop
endprogram test_save

やったね!・・・と思ったら、既にディレクトリがあるとエラーで止まっちゃうのか。ディレクトリがなかったらもちろんエラーだし・・・うーむ。「既にディレクトリがあるときはなにもせず、ない場合のみ作る」なんて、そんなシステムコールは無理か・・・?

ググッた結果、
http://www.atmarkit.co.jp/flinux/rensai/theory08/theory08a.html
を参考に、シェルスクリプトなるものを初めて利用してみる。
http://beginprogram.blog114.fc2.com/blog-entry-27.html
をほぼコピペで。「save_data という名前のディレクトリの存在を調べて、なければ作るスクリプト」は、

#!/bin/bash

CHK_DIR=save_data

if [ ! -d ${CHK_DIR} ] ; then
        mkdir ${CHK_DIR}
fi

でおk.これにたとえば mkdir_save_data.sh などと名づけて保存しておく。ここで注意。WindowsでNotepad++を使って編集している場合、改行形式がWindowsのままだとLinuxで実行できない。メニューの「編集 > EOL conversion」からUnixに変更するとちゃんと実行できるようになる。シェルスクリプトの実行は

$ sh mkdir_save_data.sh

なので、先程の F90 ソースを書き換えて、

program test_save
  implicit none
  integer :: hoge=777
  integer :: fuga=666
  real(8) :: vec(3) = (/-3.0d0, -2.0d0, -1.0d0/)
  character(len=72) :: restart_file
  
  CALL system('sh mkdir_save_data.sh') !! ディレクトリの存在を調べてなければ作るスクリプト mkdir_save_data.sh を実行する
  
  !! determine the file name
  write(restart_file,"('./save_data/restart001.save')")
  open(200,file=restart_file,status="replace",position="rewind",form="formatted")
    write(200,"(2(i9,1x))") hoge, fuga
    write(200,"(3(es20.13,1x))") vec(1:3)
  close(200)
  
  stop
endprogram test_save

でやったらうまくいったよ!