MATLABスクリプトの命名法

最初の頃はあまりこの問題を認識していなかったのですが、データが整ってきていざ解析、となってくると、日々様々なグラフを作っては検討し、という繰り返しになってきます。この段階では、[**とりわけLive Scriptを使用するのが有利**](http://qiita.com/kouichi-c-nakamura/items/6233d78180a9f5e5f4ce)です。コードと共にグラフや数値出力を保存できるので、レポート用紙やノートブックのような感覚で使えます。

このようなスタイルで色々思いつく解析を試していくと似たような、しかし少しだけ違うLive Scriptファイルがたくさんできてきます。古い解析結果も、ノートブックのような感覚で残しておきたいが、中身がほぼ同じだったりするので新しいLive Scriptファイルとの間でどうやって名前を区別するかという**「名付け親」の苦しみ**が出てくるのです。苦しみというのは大袈裟かもしれませんが、本質的ではない部分で結構知恵を使わなければならず、煩わしいものです。

# 日付に基づいた接頭辞を用いてスクリプトを命名する

[こちらの記事「解析において僕の考える最強のフォルダ構成」](http://qiita.com/sshojiro/items/67ee0b91a64aeefa46fa)を参考にしましたが、これに対する単純明快な解決法は**スクリプトファイルの名前を日付で始める**ということです。実際には数字でファイル名を始めることが許されていませんから、アルファベットで始める必要があります。私の場合はscriptなので、接頭辞scrをつけて 以下のようにしています。


```
scr2017_02_15_115520_thisisagreatscript.mlx
````
つまり「年月日時分秒」を名前の頭に持ってくるのですが（正直「秒」は不要かもしれません）、こうすると何が嬉しいのでしょうか？

+ **ほとんど似たような内容のスクリプトでも気にせずに同じ名前で日付だけ変えて保存できるので身軽**
+ 見ただけでスクリプトだと分かる（関数やクラスではない）
+ 見ただけでいつ頃の仕事だかイメージできる
+ フォルダ内に日付順にスクリプトファイルが並ぶので仕事の進捗が見えやすい

ということに尽きるかもしれません。特に感じるのは、**新しく解析を始めるときに抵抗感が少ない**のです。

よく似た方法として、`thisisagreatscript.mlx`,　`thisisagreatscript2.mlx`,` `thisisagreatscript3.mlx`, ... と接尾辞で番号を付加して対応するやり方のほうがすぐに思いつくかもしれませんが、これの欠点は、

+ 情報が少なくなる
+ フォルダ内に類似した内容のファイルがまとまって表示され、仕事の進捗が**見えにくい**。（もちろんフォルダ表示の仕方を変えれば対応できますが）
+ 一見してスクリプトなのか関数なのか**判断できない**
+ 最初に名前をつける時は**「う～ん」と考えて**よい名前をつける必要がある
+ だんだんヴァージョンが増えてきて内容が変わってきたときにどこから別の名前に切り替えようか**悩む**

これは**内容毎にグループ化して捉えるか、日付でグループ化して捉えるかの違い**、と言ってもよいと思います。野口悠紀雄の「**超整理法**」という本が昔流行りましたが、これは紙の書類を片付けるときに、内容毎に分類するのをやめて、押出しファイル形式と言って新しいものを本棚の左端に入れると決める、という提案でした。考え方としてはちょっと似ていると思います。

実感として、**私は`scr20170215_120747_*.mlx`形式に切り替えてから、飛躍的にスクリプトの数が増えました。**身軽になった分、新しい解析に取り組む敷居が下がったのだと思っています。

# 関数 `scriptname`
以下のscriptnameという関数はさらにこれを身軽にするために考えたもので、コマンドウィンドウで

```
scriptname
```
と呼び出せば
```
scr20170215_120747_*.mlx
```
と出力され、ファイルの命名を助けてくれます。

```
scriptname hoge
```
と呼び出せば
```
scr20170215_120747_hoge.mlx
```
と、出来上がった形でのスクリプト名を返してくれます。

# 結論的なスクリプトは別のルールで

[こちらの記事「解析において僕の考える最強のフォルダ構成」](http://qiita.com/sshojiro/items/67ee0b91a64aeefa46fa)の執筆者も教えてくれましたが、こうやってたくさんスクリプトを貯めると、あとから見たときにどれが一番大事だったかパッと分かりにくいという問題が生じます。

私の場合は`main_`という接頭辞をつけることにしており、`main_hoge.mlx`が最終版です。これは通常論文のための図などを意味します。

現在、私の作業フォルダには多数の`scr*.mlx`ファイルが溢れており、小数の`main_*.mlx`ファイルが混じっています。

ぜひ一度お試しください。



```matlab
function varargout = scriptname(varargin)
% scriptname prints something like 'scr2016_07_05_163045_thisscript.mlx' to
% Command Window. 
%
% Including and beginning with automatically generated serial date-time
% string in the name of script releases you from the burden of thinking of
% unique name for each script. It is also easy to see the progress and
% shift of your work over time.
%
% scriptname()
% scriptname(datenumber)
% scriptname(datenumber,name)
% newname = scriptname(_____)
%
% INPUT ARGUMENTS
% datenumber  Serial date number in double | now (default)
%             (Optional)
%
% name        char
%             (Optional) Name of the new script. Illegal charcaters will be
%             replaced with _. If you include '.m' or '.mlx' at the end of
%             name, it will be maintained. Otherwise, '.mlx' will be added
%             at the end of name.
%
% OUTPUT ARGUMENTS
% newname     Name of the new script in char. It begins with 'scr',
%             followed by date and time in the format '2016_07_01_121500_',
%             and then by 'newscriptname.mlx' or 'newscriptname.m'
%             eg. scr20160701_121500_newscriptname.mlx
%
%
% See also
% K_MATLAB_shortcuts, datename
%
% Written by Kouichi C. Nakamura Ph.D.
% MRC Brain Network Dynamics Unit
% University of Oxford
% kouichi.c.nakamura@gmail.com
% 11-Jul-2016 07:03:17


switch nargin
    case 0
        datenumber = now;
        name = '*.mlx';
    case 1
        if isa(varargin{1},'double')
            datenumber = varargin{1};
            name ='*.mlx';
        elseif ischar(varargin{1}) && isrow(varargin{1})
            datenumber = now;
            name = varargin{1};
        else
            error('The input argument is of wrong type')
        end
    case 2
        datenumber = varargin{1};
        name = varargin{2};
        
    otherwise
        error('too many input arguments')
end

if ~strcmp(name,'*.mlx')
    ext = regexp(name,'\.m(lx|)$','match');
    if isempty(ext)
        ext = '.mlx';
    else
        ext = ext{1};
    end
    namestem = regexprep(name,'\.m(lx|)$','');
    namestr = regexprep(namestem,'[^a-zA-Z0-9_]','_');
    newnamestem = [namestr,ext];
else
    newnamestem = name;
end

newname = sprintf('scr%s_%s',datename(datenumber),newnamestem);

if length(regexprep(newname,'\.[a-z]*$','')) > namelengthmax
   warning('K:scriptname:toolong',...
       'The length %d of the new name not including the file extention exceeds the max length %d allowed.',...
       length(regexprep(newname,'\.[a-z]*$','')),namelengthmax)
    
end

if nargout > 0
    varargout{1} = newname;
else
    disp(newname) %#ok<DSPS>
    clipboard('copy',newname);
end

end

%--------------------------------------------------------------------------

function s = datename(t)
% A wrapper of datestr for variable/file name
% s = datename(t)
%
% s = datestr(t,'YYYY_DD_MM_hhmmss')
%
% INPUT ARGUMENTS
% t           a datetime value
%
%
% This utility funciton may be useful in preparing a data/time-based file
% names or variable nakmes.
%
% See also
% datestr,now
%
% Written by Kouichi C. Nakamura Ph.D.
% MRC Brain Network Dynamics Unit
% University of Oxford
% kouichi.c.nakamura@gmail.com
% 30-Jun-2016 15:21:00



s = datestr(t,'yyyymmdd_HHMMSS');

end
```