シェルスクリプトを記載する時、bashで実行されることを意識する際、冒頭のシェバン (shebang) 行に
1 | #!/bin/bash |
と記載することが多いです。
Linuxではこれで全く問題ないのですが、近年の macOS の状況を見ていると、これはちょっと考え直した方がいいかなと思ってきました。
簡潔に言うと、
1 | #!/usr/bin/env bash |
とするのが汎用性の高い運用になると思います。
シェルスクリプトを記載する時、bashで実行されることを意識する際、冒頭のシェバン (shebang) 行に
1 | #!/bin/bash |
と記載することが多いです。
Linuxではこれで全く問題ないのですが、近年の macOS の状況を見ていると、これはちょっと考え直した方がいいかなと思ってきました。
簡潔に言うと、
1 | #!/usr/bin/env bash |
とするのが汎用性の高い運用になると思います。
mkdir -p
は mkdir --parents
であり、必要に応じて親ディレクトリを作成する便利なオプションです。
しかし、ふと、man を見たらもうひとつの機能があることに気づきました。それは「ディレクトリが存在していてもエラーを返さない」というものです。
私はこれまでいつもスクリプトでディレクトリを作成する際は、
1 | [[ -d some_directory ]] || mkdir some_directory |
としていました。
しかし、実は、これは
1 | mkdir -p some_directory |
で終わってしまうということですね。
小さなことですが、勉強になったので、備忘録として記録しておきます。
VirtualBox上でDebianをインストールしていろいろ試しているのですが、Guest Additionsをインストールしようとしてちょっと困ったので、備忘録として残しておきます。
1 2 | cd /media/cdrom sudo sh VBoxLinuxAdditions.run |
でいけます
最初、普通Ubuntuでやるように
1 2 | cd /media/cdrom sudo . /VBoxLinuxAdditions .run |
としたところ、
1 | sudo : unable to execute . /VBoxLinuxAdditions .run: Permission denied |
となりました。
なんでだろうと思ったところ、https://forums.virtualbox.org/viewtopic.php?t=58799にヒントが書かれていました。
cdromをマウントする際、/etc/fstabに
1 | /dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0 |
と書かれています。この noauto を exec にすることで、実行可能になるということでした。
もちろん、これを exec に変えるのも方法ですが、この場合、任意のCDが実行されてしまうリスクもはらんでいます。
それ以外の方法がないかと考えたところ、直接実行するのではなく、シェルから実行するという方法があるかなと思いました。
そうしたら、上記のリンクの最後にその旨が書かれていました。
なので、実際に試してみました。
1 2 | cd /media/cdrom sudo sh VBoxLinuxAdditions.run |
そうしたところ、あっさりと動きました。
スクリプトを直接実行ではなく、シェルから実行というのは常に頭のどこかに置いておくといいんだなということを学びました。
目的
シェルとは
シェルスクリプトとは
UNIX系OS(Linux, Mac)における基礎知識
パス(絶対パス・相対パス)
プログラミング言語は、英語の命令文に相当
ファイル名に日本語やスペースを用いない
bash基本
文字の表示(コマンド:echo)
Brace Expansionの使い方
変数(コマンド:変数=〇〇)
変数の定義
変数の利用
変数の配列処理
配列
配列の定義
配列の利用
現在いるディレクトリの確認(コマンド:pwd)
端末(ターミナル)の画面をクリア(コマンド:clear)
標準入力から変数を定義
条件分岐:If文(コマンド:if)
条件分岐:Case文(コマンド:case)
四則演算
リダイレクト(コマンド:> or >>)
ファイル内容出力(コマンド:cat)
ファイルのリスト一覧確認(コマンド:ls)
カウント(コマンド:wc -l)
パイプ [ | ](コマンド:|)と検索(コマンド:grep)
テキストファイルの作成(コマンド:touch)
フォルダの作成(コマンド:mkdir)
ファイル・フォルダのコピー(コマンド:cp)
ファイルをコピー
フォルダをコピー:オプション(-r)必須
ファイル・フォルダの移動(コマンド:mv)
ディレクトリ移動(コマンド:cd)
ファイル・フォルダの削除(コマンド:rm)
ファイルの削除
フォルダの削除:オプション(-r)必須
反復処理:For文(コマンド:for)
反復処理:While文(コマンド:while)
関数(コマンド:function)
先頭の表示(コマンド:head)
末尾の表示(コマンド:tail)
ソート処理(コマンド:sort)
重複削除(コマンド:uniq)
文字列の切り出し・抽出(コマンド:cut)
区切り文字を指定して抽出
-d: 区切り文字指定
-f: フィールドの指定
文字のインデックスを指定して抽出
-c: 先頭からの文字数
文字列の置換(コマンド:sed)
数字の連番(コマンド:seq)
コマンドのレファレンスマニュアルを表示(コマンド:man)
ワイルドカード [ * ] (コマンド:*)
タイトル通りの投稿ですが、よく忘れるので、備忘録として。
スクリプトを書いている時に、入力ファイルの改行を全部とって1行にしたいという時があります。
たとえば、
1 2 3 4 5 6 7 | seq 5 > list cat list 1 2 3 4 5 |
となっている時、これを
1 | 1 2 3 4 5 |
としたいような時をイメージしてください。
これを sed でやろうとするとうまくいきません。
1 2 | sed 's/\n//' list sed 's/\r//' list |
などでいくかと思えどうまくいかず、いろいろはまることになります。
さらにmacとLinuxでは、sedがBSDのsedとGNU sed で違うため、ここもまたはまる原因になります。
でも、sedにこだわらず、Perlで
1 | perl -pe 's/\n/ /' list |
とすると、あっさりうまくいきます。
(細かく言うと、Windowsだと、\r\nだったりしますが、とりあえず、UNIX環境と仮定します)
なお、perlのオプション -e は引数をそのままプログラムとして実行するオプションで、ワンライナーでは必須のものであり、オプション -p は、入力の各行に対してプログラムを実行し、最後に結果を表示するオプションとのことです。こちらのサイトに詳しく書いてあり、勉強になりました。
ということで、シェルスクリプトで改行の削除に困ったら、sedにこだわらず、perl -pe を活用すると迷う時間が減るかもしれません。
シェルスクリプトで作業を自動化しようとするとき、ファイル名やディレクトリ名に半角スペースが入っていると、エラーとなります。
この半角スペースを全部アンダースコア( _ ) で置き換えてあげたいと思いました。
それも、カレントディレクトリだけではなく、再帰的にサブディレクトリにあるものもすべてです。
やっぱり楽したいですから…。特に画像解析をやる場合、DICOMのディレクトリ構造は、かなり奥深くにいくので、再帰的にいけると楽になります。
スマートでないかもしれませんが、以下のようなスクリプトを書いてみました。
replace-space-underscore.shのダウンロード(右クリックで名前をつけて保存)
思考過程を書いていこうと思います。
先日、ある方と「BashからMatlabを呼び出せないだろうか」という話をしていました。もし、これができたら、シェルスクリプトから、Matlabを呼び出せるので、シェルとMatlabを完全に連携できるわけです。
結論としては、以下でできました。
Matlabのスクリプト名を sample_code.m とすると、以下でできます。
1 | $ matlab -nodesktop -nosplash -r 'sample_code; exit' |
コツは2つです。
あるプロジェクトにおいて、「MRI画像の一覧画像を作成してもらいたい」という依頼を受けました。
イメージとしては、下記のようなものです。
以前、FSLのシェルスクリプトチュートリアルを翻訳していた際に、演習に
Lightbox Viewerがあったのを思い出して、改めて、それを見ながら、さらに機能を追加したスクリプトを考えてみました。
作成しながら勉強になることがいくつもあったので、細かくわけてみたいと思います。