【fish】複数行野郎

次世代シェルである fish を使ったサンプル集です。


文字列を格納した配列変数から指定の要素を削除する
   pickup_dirlist.fish
   pickup_dirlist_2.fish
文字列のパターンマッチ判定
   match_file.fish
   match_pattern.fish
引数解析関数の使い方
   argparse.fish
複数プロセスの終了を待つ
   wait_jobs.fish

 
 
 

pickup_dirlist.fish

$TARGET_DIRS にファイルシステムの先頭が格納されている。
このうち $EXCLUDE_DIRS に存在するパスを除外したうえで find を実行する。
 

#!/usr/bin/env fish
# find 実行対象外にしたいディレクトリ一覧
set -l EXCLUDE_DIRS "/lost+found" \
                    "/snap"       \
                    "/proc"       \
                    "/sbin"       \
                    "/media"      \
                    "/root"       \
                    "/opt"        \
                    "/srv"        \
                    "/cdrom"      \
                    "/lib64"      \
                    "/mnt"        \
                    "/run"        \
                    "/tmp"        \
                    "/lib"        \
                    "/dev"        \
                    ""    # End of list

# ファイルシステム(以下は例)の先頭を動的に取得する。
set -l TARGET_DIRS  ( find / -maxdepth 1 -mindepth 1 -type d )

# TARGET_DIRS から EXCLUDE_DIRS に書かれた要素を削除する
for i in ( seq 1 (count $EXCLUDE_DIRS) )
  set TARGET_DIRS ( string replace $EXCLUDE_DIRS[$i] '' $TARGET_DIRS )
end

echo $TARGET_DIRS

# 出力結果
# /var  /sys /boot   /bin   /home   /dev /usr /etc

 
 
 

pickup_dirlist_2.fish

$TARGET_DIRS にファイルシステムの先頭が格納されている。
このうち $EXCLUDE_DIRS に存在するパスを除外したうえで find を実行するが、
事前に $EXCLUDE_DIRS の各パスの末尾にある『/』を取り除いておく。
 

#!/usr/bin/env fish
# find 実行対象外にしたいディレクトリ一覧
set -l EXCLUDE_DIRS "/lost+found/" \
                    "/snap/"       \
                    "/proc/"       \
                    "/sbin/"       \
                    "/media/"      \
                    "/root/"       \
                    "/opt/"        \
                    "/srv/"        \
                    "/cdrom/"      \
                    "/lib64/"      \
                    "/mnt/"        \
                    "/run/"        \
                    "/tmp/"        \
                    "/lib/"        \
                    "/dev/"        \
                    ""    # End of list

# ファイルシステム(以下は例)の先頭を動的に取得する。
set -l TARGET_DIRS  ( find / -maxdepth 1 -mindepth 1 -type d )

# TARGET_DIRS から EXCLUDE_DIRS に書かれた要素を削除する
for i in ( seq 1 (count $EXCLUDE_DIRS) )
  set EWORD       ( echo $EXCLUDE_DIRS[$i] | sed 's:/$::g' )      # ★
  set TARGET_DIRS ( string replace -r $EWORD '' $TARGET_DIRS )
end

echo $TARGET_DIRS

# 出力結果
# /var  /sys /boot   /bin   /home   /dev /usr /etc

 
 
 

argparse.fish

引数解析関数 argparse の使い方。
参考
 fishでのオプション解析の決定版!argparseコマンドの紹介
要点
 ロングオプション名に紐付いた変数 _flag_XXXX が自動的に作成される
その他
 私の環境では、'a/add=+' xxxx yyyy zzzz などといったように複数引数を取ることができなかった.
 (一応 -a xxxx -a yyyy -a zzzz とすれば複数の引数を取ることはできた)
 

#!/usr/bin/env fish

set    FLAG_U     0
set    FLAG_N     0

set    VERSION    1.0.1


function print_version
  echo "VERSION: $VERSION"
end


function setup
    argparse -n setup -x  'u,n'            \
                          'u/update'       \
                          'n/new'          \
                          'v/version'      \
                          -- $argv ;or return 2

    if set -lq _flag_update
      set FLAG_U    1
    else if set -lq _flag_new
      set FLAG_N    1
    else if set -lq _flag_version
      print_version
      exit 0
    end
end


function start 
  # この中で FLAG_U と FLAG_N を参照して処理を分岐させる
  echo "(FLAG_U, FLAG_N) = ($FLAG_U, $FLAG_N)"
end


function main
  setup $argv
  start
end


main  $argv

 
 
 

match_file.fish

file コマンドでファイル種別を識別し、それに応じたアプリを使って操作する
なお、string コマンドは fish の組み込み関数である。
 

#!/usr/bin/env fish

if test -z {$argv[1]}
  echo '$argv[1] was empty...'  >&2
  exit 2
else if test ! -e {$argv[1]}
  echo "$argv[1]: no such file" >&2
  exit 2
end

set -l  MY_EDITOR   "nvim"
set -l  MY_OPEN     "xdg-open"
set -l  ftype ( file -b -i $argv[1] )

switch $ftype
  case "text/*"
    eval $MY_EDITOR   $argv[1]
  case "application/x-executable*charset=binary"  # binary file
    eval builtin string ' ' "fish" "-c" "$argv[1]"
  case "*x-empty*"  # empty file
    echo 'SKIP: $argv[1]: empty file...'
  case "*"
    eval $MY_OPEN $argv[1]
end 

 

match_pattern.fish

$TOGGLE_DEBUG_MODE 変数が true, TRUE, enable, ENABLE, 1 であるか判定する.
なお、string コマンドは fish の組み込み関数である。
 

#!/usr/bin/env fish

if test ( string match -r -i "\A[t|e|1]" "$TOGGLE_DEBUG_MODE" )
  echo xxxx
else 
  echo yyyy
end

 
 
 

wait_jobs.fish

my_script_1.sh、my_script_2.sh、my_script_3.sh、my_script_4.sh、
を並列で実行させて、全ての終了を待つ。
 

#!/usr/bin/env fish
for i in ( seq 1 4 )
  sh my_script_$i.sh &
end

# wait for the job to finish
while true
  set -l bg_jobs ( builtin jobs -p 2>/dev/null )
  sleep 0.5
end

echo Finished.