「シェルスクリプトの基礎 - 外部コマンド」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
(文字列「__FORCETOC__」を「{{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This pag…)
 
45行目: 45行目:
  fi
  fi
  </syntaxhighlight>
  </syntaxhighlight>
<br>
==== whichコマンド ====
whichコマンドの標準エラー出力を抑制して、コマンドの存在確認を行う。<br>
<syntaxhighlight lang="sh">
which <コマンド名> 2>/dev/null
</syntaxhighlight>
<br>
<syntaxhighlight lang="sh">
# 例 : gitコマンドのパスを確認
#      存在する場合のみパスを表示
which git 2>/dev/null
# 例 : 存在しないコマンドを確認
#      何も表示されない
which nonexistentcommand 2>/dev/null
</syntaxhighlight>
<br>
また、コマンドの存在確認を条件分岐に使用することもできる。<br>
<syntaxhighlight lang="sh">
# gitコマンドが存在するか確認
if which git >/dev/null 2>&1; then
    echo "gitコマンドが利用可能です"
else
    echo "gitコマンドが見つかりません"
fi
</syntaxhighlight>
<br>
以下の例で使用している<code>>/dev/null 2>&1</code>は、標準出力を破棄して、標準エラー出力を標準出力と同じ場所 (この例では、/dev/null) にリダイレクトする。<br>
これにより、whichコマンドの出力を完全に抑制しながら、コマンドの存在を確認することが可能となる。<br>
<br><br>
<br><br>



2025年1月6日 (月) 23:16時点における最新版

概要

シェルスクリプトにおいて、外部コマンドを使用する必要がある場合、その外部コマンドが使用可否を調べておくと便利である。


外部コマンドの使用可否

type -Pコマンド

以下の例では、pythonコマンドの使用可否を確認している。

type -P <コマンド名>は、環境パスで指定されたディレクトリから<コマンド名>を検索して、そのフルパスを取得するが、
ここでは、<コマンド名>の使用可否を確認するために利用している。

そのまま実行すると<コマンド名のフルパスが出力されるので、/dev/nullデバイスへリダイレクトして、出力を抑制している。

 if type -P python > /dev/null; then
    echo "python コマンドを使用できます"
 else
    echo "python コマンドが見つかりません"
 fi


また、指定した外部コマンドが使用できない場合、シェルスクリプトを終了させるには、以下のように記述すればよい。
条件式を!で反転させていることに注意すること。

また、echoの出力を>&2とリダイレクトすると、標準エラー出力へ出力できる。

 if ! type -P python3 > /dev/null; then
    echo 'This script requires Python 3. Please install Python 3 first and try again.' >&2
    exit -1
 fi


command -vコマンド

以下の例では、aplayコマンドの存在を確認して、存在する場合はWAVファイルを再生している。

 # aplayコマンドの存在を確認
 if command -v aplay &> /dev/null; then
    # aplayコマンドが存在する場合、指定されたファイルが存在するか確認して、存在すれば再生
    if [ -f $HOME/Login.wav ]; then
       aplay $HOME/Login.wav
    else
       echo "音声ファイルが見つかりません"
    fi
 else
    echo "aplayコマンドが見つかりません"
 fi


whichコマンド

whichコマンドの標準エラー出力を抑制して、コマンドの存在確認を行う。

 which <コマンド名> 2>/dev/null


 # 例 : gitコマンドのパスを確認
 #      存在する場合のみパスを表示
 which git 2>/dev/null
 
 # 例 : 存在しないコマンドを確認 
 #      何も表示されない
 which nonexistentcommand 2>/dev/null


また、コマンドの存在確認を条件分岐に使用することもできる。

 # gitコマンドが存在するか確認
 if which git >/dev/null 2>&1; then
    echo "gitコマンドが利用可能です"
 else
    echo "gitコマンドが見つかりません"
 fi


以下の例で使用している>/dev/null 2>&1は、標準出力を破棄して、標準エラー出力を標準出力と同じ場所 (この例では、/dev/null) にリダイレクトする。
これにより、whichコマンドの出力を完全に抑制しながら、コマンドの存在を確認することが可能となる。


外部コマンドの出力と変数

lsgrepfind等のコマンドの実行結果を変数に代入するには、以下のように記述する。

変数=$(コマンド)
または
変数=`コマンド`


以下の例では、lsコマンドの実行結果を変数FILESに代入して、echoで出力している。

 #!/bin/sh
 
 FILES=$(ls)
 echo "$FILES"

または

 #!/bin/sh
 
 FILES=`ls`
 echo "$FILES"



パイプとwhile readコマンド

find . -name '*.sh'等の外部コマンドの出力結果を1行ずつ処理するには、パイプwhile readコマンドに接続して記述する。

以下の例では、カレントディレクトリ下の.shファイルを再帰的に列挙している。

 find . -name '*.sh' | while read SHFILE; do
    echo "$SHFILE"
 done



外部コマンドの出力と配列

パイプを使用せず、`コマンド名`または$(コマンド名)で実行した外部コマンドの出力を、配列で受け取る方法もある。

forループのinの後の変数(以下の例では、変数SHFILES)には、スペース区切りで各要素が列挙される。
変数SHFILESの値にスペースが含まれる場合、行を1つの要素として処理するためには、変数をダブルクォーテーションで囲む必要がある。

 SHFILES=$(find . -name '*.sh')
 
 for SHFILE in "$SHFILES"; do
    echo "$SHFILE"
 done



日時

dateコマンドを使用すると、現在時刻を表す文字列を自由なフォーマットで取得することができる。
例えば、時刻入りの簡単なログを出力する場合やバックアップを作成する時のファイル名の構成のために使用する。

以下の例では、dateコマンドを使用して、日付からYYYYMMDD-HHMMSSのような文字列を作成している。

date +%Y%m%d-%H%M%S

20200101-083015


以下の例では、現在日時をファイル名に付加してファイルのコピー(バックアップ)を行っている。

cp Sample.txt Sample_`date +%Y%m%d`.txt

# 出力
ls
Sample.txt
Sample_20050102.txt