恥は/dev/nullへ by 初心者

プログラミング初心者がのろのろと学んだことをつづっています♪

$HOME/binまたは$HOME/.local/bin

自作スクリプトを置いておく場所として、ホームディレクトリに

.bin

というディレクトリを用意しようと思ったのですが、Debian開発者様たちは最初からそういった使い方を見越しているようで、Debian 11の.profileに以下の記述がありました。

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
    PATH="$HOME/.local/bin:$PATH"
fi


この記述を見ると、ホームディレクトリに「bin」ディレクトリを作成するか、ホームディレクトリにある「.local」ディレクトリの直下に「bin」ディレクトリを作成して、その中に実行権限を付与したシェルスクリプトを置けば良さそうです。

そんなわけで、

mkdir .local/bin

とした後で

source ~/.profile

を実行しました。

あとは、この「.local/bin」ディレクトリに自作スクリプトを配置するだけです。
Debian様、非常に便利ですね。ありがたや〜。

ffmpegでmp4ファイルをmp3ファイルに変換

動画(mp4形式)から音だけを抽出したいと思いネット検索をしてみました。ffmpegというソフトを使えばmp4ファイルからmp3ファイルを作成できるようです。
なお、以下の作業はDebian 11(bullseye)で行いました。

ffmpegの使用例

変換前のmp4ファイルが「hoge.mp4」で、変換後のmp3ファイルが「hoge.mp3」であるとすると、コマンドラインは以下のようになります。

ffmpeg -i hoge.mp4 hoge.mp3

出来上がったmp3ファイルを調べたところ、ビットレートは128kb/sでした。

ビットレート256kb/sにするのであれば次のようにします。

ffmpeg -i hoge.mp4 -ab 256k hoge.mp3


変換用スクリプト

少し時間が経てばビットレートの指定の仕方も忘れてしまいますので、シェルスクリプトにしてみました(普段シェルスクリプトを書かないので、どこか間違っているかもしれませんが)。

#!/bin/bash

if [ $# -eq 0 ]; then
    echo "引数を指定してください"
    exit 1
elif [ $# -ne 1 ]; then
    echo "引数は1つだけしか指定できません"
    exit 1
fi

INPUT=$1

if [ "$INPUT" != *.mp4 ]; then
    echo "拡張子が.mp4ではない気が・・・?"
    exit 1
fi

OUTPUT=${INPUT/%.mp4/.mp3}

if ffmpeg -i "$INPUT" -ab 256k "$OUTPUT"; then
    echo
    echo "変換が終わったぞよ(MP4 → MP3)"
    exit 0
else
    STATUS=$?
    echo
    echo "なんか、変換できんかったわ"
    echo "exit status : $STATUS"
    exit $STATUS
fi

$1をそのまま使えば INPUT という変数を用意する必要はないのですが、私の好みでINPUTを用意しています。

スクリプトの使い方

上記シェルスクリプトを「mp4tomp3.sh」というファイル名で保存して実行権限を付与したとします。引数としてmp4ファイルを1つ指定します。

./mp4tomp3.sh hoge.mp4

これで「hoge.mp3」というファイルが出来上がります。

[MQL5]CopyBuffer関数に登場するバッファ番号とは?

インジケーターを作成する場合などに使うCopyBufferという関数には、引数の1つとして buffer_num(バッファ番号)というものがあります。


CopyBufferの書式の1つを引用すると

int CopyBuffer( 
    int       indicator_handle,     // indicator handle 
    int       buffer_num,           // indicator buffer number 
    int       start_pos,            // start position
    int       count,                // amount to copy 
    double    buffer[]              // target array to copy 
);

となっており、buffer_num の行には「indicator buffer number」というコメントが書かれています。

CopyBuffer関数のヘルプを初めて読んだ時は、この buffer_numが何なのかよく分かりませんでした。そこで、ネット情報を調べた結果、 各インジケーター関数が持っているバッファの番号である(SetIndexBufer関数内で指定したバッファ 番号ではない)ことが分かりました。


このことに気づかせてくれたのは、以下のページに載っていたやり取りでした。 https://www.mql5.com/en/forum/319420


上記ページにおいて、質問者は2つの移動平均線をチャートに表示しようとしています。そして、質問者が投稿したコードには

// 行数を減らすために編集してあります。

int copiedAmount_1 = CopyBuffer(handle_1, 0, 0, rates_total, buffer_1);
        (中略)
int copiedAmount_2 = CopyBuffer(handle_2, 1, 0, rates_total, buffer_2);

という部分があり、最初に登場するCopyBuffer関数の第2引数は「0」で、次に登場するCopyBuffer関数の第2引数は「1」になっています。


このコードに対して、他の人が「iMA関数には1つのバッファしかない」という趣旨の返信をしていました。 これは、バッファ番号は0から始まるので、1つのバッファしか持たないiMA関数のバッファ番号として 1 はおかしい(iMA関数のバッファ番号は 0 だけ)という意味です。

このことはインジケーター関数のヘルプを読むことで確認することができます。


iMA関数のヘルプを見てみましょう。すると、次のようにiMA関数には1つのバッファしかないことが記載されています。

The function returns the handle of the Moving Average indicator. It has only one buffer.  


ついでに、iStochastic関数のヘルプを見ると

Note
  The buffer numbers: 0 - MAIN_LINE, 1 - SIGNAL_LINE.  

という記述がありました。このことから、iStochastic関数には2つのバッファがあることが分かります。
ストキャスティクスのメインラインの値を取得する場合はCopyBufferの第2引数に 0 を指定し、 シグナルラインの値を取得する場合はCopyBufferの第2引数に 1 を指定することになります。


最後に、iBands関数のヘルプを見てみましょう。

Note
  The buffer numbers are the following: 0 - BASE_LINE, 1 - UPPER_BAND, 2 - LOWER_BAND  

という記述があることから、iBands関数には3つのバッファがあると分かります。

ボリンジャーバンドのミドルラインの値を取得する場合はCopyBuffer関数の第2引数に 0 を指定し、 アッパーラインの値を取得する場合はCopyBuffer関数の第2引数に 1 を指定し、 ロウアーラインの値を取得する場合はCopyBuffer関数の第2引数に 2 を指定することになります。


indicator buffer という表現が紛らわしいような?

CopyBuffer関数のヘルプにおいて、「indicator buffer」という表現が異なる意味合いで複数回登場することが紛らわしいと感じました。


冒頭に引用したCopyBuffer関数の書式に登場する「indicator buffer number」の「indicator」という語は iMA関数やiStochastic関数など、特定のテクニカル指標を計算する関数を指しています。よって、この「indicator buffer」は、「特定のテクニカル指標を計算する関数に付属しているバッファ」という意味です。


その一方で、CopyBuffer関数のヘルプには以下の文章も登場します。

When copying the yet unknown amount of data, it is recommended to use
a dynamic array as a buffer[] recipient buffer, because the CopyBuffer() 
function tries to allocate the size of the receiving array to the size of 
the copied data. If an indicator buffer(array that is pre-allocated for 
storing indicator values by the SetIndexBufer() function) is used as 
the buffer[] recipient array, partial copying is allowed.

4行目に「indicator buffer」という表現がありますね。
それに続く括弧の中を読むと、「indicator buffer」の説明として「インジケーターの値を格納するために SetIndexBufer関数によって事前に割り当てられた配列」と書かれています。


すなわち、この文章においては、先述した「indicator buffer」(特定のテクニカル指標を計算する関数が持つバッファ)とは違う意味で、「indicator buffer」という表現が使われています。このことが、場合によっては、ヘルプを読む人に誤解を与えているのではないかと感じました。


なお、上記の文章の大雑把な内容は以下のとおりです。

もし複製するデータの量(サイズ)がまだ分からないのなら、データを受け取る側のバッファ配列には動的配列を使うとよい。 というのも、CopyBuffer関数は、受け側の配列のサイズと同じ量のデータを複製しようとするからである。
(備考)受け取る側の配列のサイズがコピー量の基準となる。


一方、受け側の配列がインジケーターバッファ(事前にSetIndexBuffer関数を使って割り当てた配列で、インジケーターの値を保存するためのもの )ならば、部分的な複製をすることができる。

(備考)部分的な複製とは、受け取る側の配列のサイズより少ない量を複製すること。

Slackware15で日本語入力

Slackware15をインストールしてみました。とりあえずデフォルトのままでもstartxすればxfceが起動して最低限のことはできそうです。しかし、日本語入力ができなかったので、まずは日本語入力の設定をすることにしました。

デスクトップを起動している設定ファイルはどこ?

ここ数年Debian系しか使ったことがないので、Slackwareについてはチンプンカンプンです。そこで、 Debianと同じように.xinitrcをホームディレクトリに用意して、その中にfcitxに関する記述をしました。

export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx
fictx &

これでstartxを実行したら、デスクトップ(xfce)が起動しませんでした。当然ですよね。xfceを起動するための記述がありませんから(汗)。

そこで、xfceの起動はどの設定ファイルにもとづいて行われているのか知るべくstartxについて調べることにしました。

which startx

を実行したら

/usr/bin/startx

と表示されたので、このファイルの中身を見ると

userclientrc=$HOME/.xinitrc
sysclientrc=/etc/X11/xinit/xinitrc

(中略)

# process client arguments
if [ x"$client" = x ]; then
    client=$defaultclient

    # For compatibility reasons, only use startxrc if there were no client command line arguments
    if [ x"$clientargs" = x ]; then
        if [ -f "$userclientrc" ]; then
            client=$userclientrc
        elif [ -f "$sysclientrc" ]; then
            client=$sysclientrc
        fi
    fi
fi

という部分が目に留まりました。

どうやらユーザーのホームディレクトリに.xinitrcファイルがある場合はその内容が読み込まれ、無い場合は/etc/X11/xinit/にあるxinitrcファイルが読み込まれるようです。

/etc/X11/xinitにあるxinitrcを開くと、最後の方に

exec /usr/bin/startxfce4

という記述があったので、ここでxfceを起動していたことが分かりました。

そこで、ホームディレクトリの.xinitrcに

startxfce4

を追記してstartxを実行したら、xfceが起動しました。

.xinitrcの設定

Slackwareに関してもLinuxに関しても素人なので、/etc/X11/xinitにあったxinitrcの内容を一通り踏襲することにしました。

そんなわけで、/etc/X11/xinitにあったxinitrcをホームディレクトリにコピーして、fcitxに関する記述を追記しました。

#!/bin/sh

########################################################################
##  Merge in defaults and keymaps                                     ##
########################################################################

userresources=$HOME/.Xresources
usermodmap=$HOME/.Xmodmap
sysresources=/etc/X11/xinit/.Xresources
sysmodmap=/etc/X11/xinit/.Xmodmap

if [ -f $sysresources ]; then
    /usr/bin/xrdb -merge $sysresources
fi

if [ -f $sysmodmap ]; then
    /usr/bin/xmodmap $sysmodmap
fi

if [ -f $userresources ]; then
    /usr/bin/xrdb -merge $userresources
fi

if [ -f $usermodmap ]; then
    /usr/bin/xmodmap $usermodmap
fi

########################################################################
## fcitx
########################################################################
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx
fcitx &

########################################################################
##  Start xfce Desktop Environment                                    ##
########################################################################

exec /usr/bin/startxfce4


fcitxの設定

.xinitrcが上述のようになっていれば X Windowを起動した時点でfcitxは動いているので、あとは日本語入力のON/OFFについて設定するだけです。

ターミナルで

fcitx-configtool

と入力してEnterを押すと設定ツールが起動します。

その後の作業は以下のページの「fcitx-mozcの設定」に書いたのとほぼ同じでした。 https://uhoho.hatenablog.jp/entry/2021/08/29/040523


唯一の違いは、mozcが見当たらなかったので代わりにAnthyを選択したことくらいです。

DebianにVirtualBox Guest Addtionsをインストール

VirtualBox Guest Addtionsをインストールしてみました。終わってから振り返れば別に難しくはないのですが、ほんのり手こずったので作業メモを残すことにしました。

環境

ホストOS:Windows10
ゲストOS:Debian11

事前準備

ネット情報によると、VirtualBox Guest Additionsをインストールするには、事前に以下のものをインストールしておく必要があるようです。

・dkmsフレームワーク  
・ビルドツール  
・カーネルヘッダー  


それらがインストールされているか調べるために

apt list --installed dkms build-essential linux-headers-$(uname -r)

を実行したところ、次のように表示されました。

Listing... Done
build-essential/stable,now 12.9 amd64 [installed]
dkms/stable,now 2.8.4-3 all [installed]
linux-headers-5.10.0-11-amd64/stable-security,now 5.10.92-1 amd64 [installed,automatic]

どうやら、私の環境では3つともインストール済だったようです。

ちなみに、インストールされていない場合は、次のようにしてインストールしておく必要があります。

apt update
apt upgrade
apt install dkms build-essential linux-headers-$(uname -r)


インストール手順

まず、Debianが動いているVirtual Boxのメニューから以下を選択します。

「デバイス」→「Guest Additions CDイメージの挿入」

次に、Guest AdditionsのCDイメージをマウントします。

mount /dev/cdrom /media/cdrom

マウント先に移動して、VBoxLinuxAdditions.runというスクリプトを実行します。

cd /media/cdrom
./VBoxLinuxAdditions.run

最後にDebian再起動します。

shutdown -r now


以上でGuest Additionsのインストールは完了です。

参考にしたウェブサイト

1.https://www.virtualbox.org/manual/
2.https://kifarunix.com/install-virtualbox-guest-additions-on-debian-11/

1はvirtualbox.orgにあるマニュアルなので信用はできるのですが、フォントが読みにくいです^^;。一方、2はHow To系のブログです。手順が簡潔にまとめられていて読みやすいです。

sudoを使えるようにする and ディレクトリ名を英語表記にする

Ubuntuを入れていたPCにDebian 11をインストールしました。デフォルトのままなので、当然ながら一般ユーザーでsudoが使えませんし、ホームディレクトリにある各ディレクトリの名前はカタカナ表記になっています。

いつものことですが、毎回やっているのに設定の仕方を覚えていません(汗)。 今後も同じことを繰り返すでしょうから、この件もブログに備忘録を残すことにしました。

一般ユーザーにsudoを実行する権限を与える

手動で/etc/groupファイルを書き換えてもよいのかもしれませんが、無難にgpasswdコマンドを使います。

たとえば、hogeという一般ユーザーがsudoを実行できるようにするのであれば、rootユーザーになって

gpasswd -a hoge sudo

を実行します。

その後、ログインし直すと、hogeがsudoを実行できるようになっています。

ディレクトリ名を英語にする

ロケールその他を日本語としてDebianをインストールすると、一般ユーザーのホームディレクトリにあるディレクトリ名が

デスクトップ  
ダウンロード  
ドキュメント 

などになっています。
これらを英語表記にする方法を調べたところ、以下のページを見つけました。

Debian系でディレクトリ名を英語にしよう」
https://qiita.com/saru_cololado/items/8b4e7f53e58a98e6c883

このページの説明によるとxdg-user-dirs-gtkというものを使えば良いみたいです。

まず、xdg-user-dirs-gtkをインストールします。

sudo apt install xdg-user-dirs-gtk

次に、以下のコマンドを実行します。

LANG=C xdg-user-dirs-gtk-update

上記コマンドを実行したら登場するウィンドウでディレクトリ名を英語表記にするか聞かれますので、「update name」を選びます。

youtube-dlで動画をダウンロード on Debian

youtube-dlというソフトを使ってみました。

youtube-dlに関するウェブサイト

https://yt-dl.org/
https://github.com/ytdl-org/youtube-dl

youtube-dlのインストール

curlコマンドを使うので、curlコマンドがインストールされていない場合は、先に

sudo apt install curl

を実行しておきます。

curlコマンドでyoutube-dlを取ってきて、/usr/binに配置します。

sudo curl -L https://yt-dl.org/downloads/latest/youtube-dl -o /usr/local/bin/youtube-dl
sudo chmod a+rx /usr/local/bin/youtube-dl

個人的には、バイナリファイルなので少し心配です。
ウィルス対策ソフトでチェックしたいような・・・。

おや?pythonについてエラーが・・・

インストールが終わり、試しにyoutube-dlコマンドを実行してみたら、以下のエラーが出ました。

/usr/bin/env: `python': そのようなファイルやディレクトリはありません


ネット検索をしたところ、/usr/bin/pythonが無いことでこの事象が起きたという記事を見つけました。そこで/usr/binの中を調べてみると、以下の2つはあるものの、「python」というファイルはありませんでした。

python3
python3.9

ちなみに、python3はpython3.9へのシンボリックリンクでした。

そこで、lnコマンドでpythonというシンボリックリンクを作りました。

sudo ln -s /usr/bin/python3 /usr/bin/python


もう一度youtube-dlコマンドを実行した所、エラーは表示されませんでした。
どうやら解決したようです。


mp4形式でダウンロードするには?

オプションを付けずにyoutube-dlを使って動画をダウンロードしたら、mkv形式でダウンロードされました。個人的にはmp4形式の方が便利なので、以下のオプションを使うことにしました。

-f mp4

これで、mp4形式でダウンロードされます。

ファイル名を「タイトル.拡張子」にするには?

他にも気になることがありました。ダウンロードしたファイルの名前に謎の文字列が含まれています。それが何なのかは調べませんでしたが、動画のタイトル.拡張子という形にしたかったので、以下のオプションを指定しました。

-o '%(title)s.%(ext)s'

これで、たとえば「マクロ経済学入門.mp4」のようなファイル名となります。

使用例

上述したことを踏まえたコマンドライン例は以下のとおりです。

youtube-dl -o '%(title)s.%(ext)s' -f mp4 URL

URLという部分に動画のURLを指定します。

ファイル名には任意の文字列を付け足すこともできます。ファイル名の先頭に

No_1_

を付け足したい場合は、次のようにします。

youtube-dl -o 'No-1_%(title)s.%(ext)s' -f mp4 URL


複数のファイルをダウンロードする

複数のファイルをダウンロードする場合は、youtube-dlコマンドを書き並べたスクリプトを使った方が楽かなと思います。

youtube-dl -o 'No_1_%(title)s.%(ext)s' -f mp4 URL
youtube-dl -o 'No_2_%(title)s.%(ext)s' -f mp4 URL
youtube-dl -o 'No_3_%(title)s.%(ext)s' -f mp4 URL
youtube-dl -o 'No_4_%(title)s.%(ext)s' -f mp4 URL
youtube-dl -o 'No_5_%(title)s.%(ext)s' -f mp4 URL
wait
printf '\a'
printf 'ダウンロードが完了しました\n'

5つの動画をダウンロードした後でビープ音を鳴らし、画面に「ダウンロードが完了しました」というメッセージを表示します。

困っていること

上述したスクリプトを生成するためのスクリプトを書こうとしたのですが、自分の知識が足らず、ダウンロードしたい動画のURLを取ってくる方法が分かりませんでした。

URL部分以外は以下のスクリプトで実現できますが、これだとURL部分を手でコピペする手間がかかるんですよね・・・(^^;。

for((i=1;i<=5;i++));do
    echo "youtube-dl -o 'No_"$i"_%(title)s.%(ext)s' -f mp4 "
done

echo wait
echo "printf '\a'"
echo "printf 'ダウンロードが完了しました\n'"