はじめに
この記事は「HTC Advent Calendar 2020」の21日目の記事です。
今回はfishについて書いていこうと思います。(fish公式サイト)
fishはshellの1つであり、「the friendly interactive shell」の略称です。
私はあまりshellに詳しいわけではないですが、fishを利用している理由はサジェスチョン機能が強力だからです。
めちゃくちゃfishが好きというわけでもないですし、bash、 zeshに精通してるわけでもないです。
過去にrmコマンドで大失敗をした経験がるのでrmコマンドをそのままにしておくのは危険だと思い、自作関数を作ってみることにしました。
fishとは
あまり細かいことは説明しないので、興味のある方はfishの公式サイトをご確認ください。
ちなみに、公式サイトには「fish is a smart and user-friendly command line shell」と記載されています。
なにを持ってユーザーフレンドリーなのかはよくわかりませんが、オートサジェスチョン機能はとても便利だと、fishを使っていて思っています。
結論
あまり説明する内容もないので、最初に結論を書きます。
fishを使っていて、rmコマンドで指定したファイルをゴミ箱に移動させたいという方は、下記のコードをコピペしたら動きます!動くはずです。。。動かなかったら申し訳ありません。
※fish限定なので、bashなどでは利用できません。その辺はご容赦ください。
使用方法としては~/.config/fish/functions
にrm.fish
というファイルを作成して、下記のコードを貼り付けるだけです。
function rm -d"send to trash"
# 削除したいファイルを取得
set trashfile (string split / $argv)[-1]
set backupnum 1
set backupfile (string join "" $trashfile ".bak~" $backupnum)
# ファイルが既にゴミ箱にある場合ループ処理
while test -f $HOME/.Trash/$backupfile
# 1世代分更新
set backupnum (math $backupnum + 1)
set backupfile (string join "" $trashfile ".bak~" $backupnum)
end
set trashfilepath (string join "" $HOME/.Trash/ $backupfile)
mv $argv $trashfilepath
echo '【DONE】'$argv 'send to trash'
end
内容説明
function <関数名>
とすることでコンソール上で作成した関数名で呼び出すことができます。今回はrm
という関数名をつけています。
-d"send to trash"
は関数の詳細を記載しておくことができます。-d
は--description
の略です。
function rm -d"send to trash"
// ... 略
end
関数に渡した引数は$argv
で取り出すことができます。
set trashfile
で変数を宣言しています。
fishでは文字列操作も簡単に行うことができます。
string split <区切り文字> <文字列>
とすることで、各文字列を指定した区切り文字列で分割することができます。
ここではパスを分割し、リストの最後を指定することで、削除したいファイルだけ取得しています。
例えば、$args
がhoge/huga/trash.txt
のような値だった場合、trash.txt
の部分だけを取り出すことができます。
set trashfile (string split / $argv)[-1]
先ほどはstring split
で文字列の分割を行いましたが、string join <区切り文字> <文字列>
とすることで、各文字列を指定した区切り文字列で結合することができます。
ゴミ箱に移動するだけでは、同じファイル名の場合に更新されてしまうので、bak~<世代番号>
としてゴミ箱に移動したあとも世代管理が出来る様にしています。
例えば、$trashfile
がtrash.txt
だとすると、trash.txt.bak~1
というようになります。
set backupnum 1
set backupfile (string join "" $trashfile ".bak~" $backupnum)
fishではもちろんwhile文も利用できます。そしてtest -f
でファイルが存在するかの確認を行うことができます。
この場合、削除したいファイルがゴミ箱にあるかを評価しています。ない場合はwhile文で処理が繰り返されます。
math
を使用することで、文字列を数値として読み取ることができます。
同じファイル名があった場合は世代数をインクリメントし、string join
を使用してファイル名を変更します。
例えばtrash.txt.bak~1
が既にゴミ箱にある場合は、trash.txt.bak~2
というようになります。
# ファイルが既にゴミ箱にある場合ループ処理
while test -f $HOME/.Trash/$backupfile
# 1世代分更新
set backupnum (math $backupnum + 1)
set backupfile (string join "" $trashfile ".bak~" $backupnum)
end
世代の更新が完了したらstring join
でゴミ箱のパス($HOME/.Trash/
)と削除したいファイル名を結合します。
あとはmvコマンドを実行することで、引数として渡したファイルを世代管理した状態でゴミ箱に移動することができます。
set trashfilepath (string join "" $HOME/.Trash/ $backupfile)
mv $argv $trashfilepath
echo '【DONE】'$argv 'send to trash'
まとめ
今回はfishを使って自作関数を作ってみました。
今まではshellって難しそうと思い敬遠していましが、やってみると意外と簡単にできました。(あまり難しいことをしていないからかもしれませんが。。)
これからはrmコマンドで失敗することもありませんし、同じファイルを何度も消してしまっても世代管理をしているので簡単に復元することができます。
ただ、今回のコードでは複数ファイルを引数に渡して削除するということはできない仕様になっているので、機会があればそちらも実装していきたいと思っています。