【す】ただ単純にバックアップしたいだけBashスクリプト拗らす

2025年4月4日プライベートbash,linux,script,ubuntu,vi

image

追記:( ^ω^)おっおっおっ

追記:動作確認

追記:そろそろ公開?

追記:動作テストにも罠test

追記:謎が一つづつ解決true/false

追記:おざなり過ぎだったBash

追記:いまさら気付く配列の悪魔

追記:やっと元に戻せた

追記:VSCodeに移って遅れた分を挽回

追記:突然訪れた惨劇・・・

追記:その後の様子

定期的に自動でバックアップしようかな・・と、以前から考えてて。

先月くらいから、未だに完成せずに毎日時間を見つけては、書いてます。

(;´∀`)

1.単純にコマンドを羅列したものを書く

2.暗号とか、ちょっとだけ背伸びする

3.エラー処理とかBashで書いてみたり

4.関数なんかも書けるんだと気付く

5.Bash沼に片足入ってしまう

シェルスクリプトとか、古臭いイメージで、いまさらこれを覚えるつもりなんて毛頭なかったんですが、1個調べると、新しい発見が出てきては、試してみたくなり・・の繰り返し。

(;´Д`) おわんねぇ

やってる事は、ほんとに、TARして暗号化してるだけというw

シェル上で動くものを、プログラミング言語のように書く(あくまでシェル)という不思議さも相まって、なんだか、面白い。

変数展開の${ }の膨大な機能部分だけでも、一見の価値アリです。

正規表現やらエラー処理、置換、文字加工など、こんな事も出来んの?と驚く(ただし、記号だらけで覚えられない)

_ab=/home/user/test.txt

${_ab} なら、/home/user/test.txt

${_ab%/*} だと、/home/user(ディレクトリ部)

${_ab##*/} だと、test.txt(ファイル名)

${_ab##*.} だと、txt(拡張子)

${_ab:-hoge} だと、_abが未定義なら、hoge

${_ab:?error} だと、_abが未定義なら、エラー

前からを"%"、後ろからを"#"、%%と2個続ければ最長というような見かたをするそう。上の例だと、"/"が出現するまで検索した結果。正規表現に触れたことがあれば、”なんとなく”分かるでしょう。

いずれにしても、3日経ったら、絶対忘れる内容ですw

※素直に、コマンド使った方がメンテ的に良い説(dirname/basenameとか)

あるコマンド出力の中身を取得したい時(複雑)とかで、awkが使われるんですね。聞いた事はあったが、こういう事かと気付かされた。

※空白区切りという条件で、何番目という感じで取れる

しかも、今回は、ゼロからターミナル越しのviエディタだけで書いてまして、いままでオザナリだった、細かなvi操作も覚えてしまおうという縛りにしてる。

※やっぱ、h/j/k/lは慣れない

(゚∀゚)

先月位から、TeraTermから、Windowsターミナル(SSH)に移行しましたが、全然問題無いです、ってか、変な挙動も無いし、こっちの方が便利かも。

しょぼスクリプトですが、完成したら、こっそり公開します。

追記:その後の様子

image

1行で出来る事を、824行ものスクリプトに水ぶくれさせてやりましたw

(;´∀`)

あとは、細かな所まで動作確認してリリース出来そうで御座います。

需要なんてなさそうですが、メンテや先人達のご享受を頂ける事も考えてgithubにこっそり置こうかなとも思っております。

クセはあるが、プログラミングライクに思い付きで手軽に書けるので、これはアリですよ。

追記:突然訪れた惨劇・・・

image

ターミナルを横に置いて、シェルの動作を確認しながらコードを書いているんですが。

そう、この日は、桜満開の休日、集中してなかったんでしょうね。

ポテチとコーヒーを啄みながら動画見つつ、ポチポチとコードを書いていたんです。

(;´∀`)

配列の数はどうやって見るんだっけ?とか、その時の俺は、何気にこんなので試してたらしい。

echo $((${#array[@]}+1)) > backup.sh

∑(゚Д゚ノ)ノ

気付いた時には、もうお寿司(4人前特上級)。

今までコツコツ書いてきたコードが、全て消えてもうた。。

もちろん、Git管理とかバックアップなんて取ってませんし(趣味の思い付きの延長だった訳で)

うん、やっぱバックアップ大事なんだな、と前向きに考える事にしよう。

(´;ω;`)

不幸中の幸い、1週間前にコピーしてたファイルが見つかった。とはいえ、1週間分が消えた。

vimをデフォのまんま使ってましたが、バックアップ設定を有効に、そろそろgit運用に移行しよう。うん

ちなみに、前回から、さらに機能拡張して1000行超えちゃってたんですよね。

ほぼほぼ完成してたのに、あーーーもったいない。

(注:明日、バースデー)

追記:VSCodeに移って遅れた分を挽回

image

運良くコピーしてたコードを見るに、相当戻ってしまった(600行位の時)

失った分を取り返すべくVSCodeで書く、Gitでがっつり管理。

根っからのWindowsユーザーなので、やっぱこっちの方がヤりやすい。

だがしかし、どうにも馴染めない。なんでだ。

フォントは合わせたし、配色テーマだろうか。

vimのテーマ、今見るとmonokaiにしてたらしいので、VSCodeでも同じ風なものに変えようと探したんですが、これが無いんですよね。。

(;´Д`)

いまいちシックリこない。

image

bashlingというテーマで落ち着きました。

一番雰囲気が似てる、ような気がする。

追記:やっと元に戻せた

image

微かに残った記憶から、何とか多分元に戻せた。

(;´∀`)

まだ、800行ですけど。前より効率的に書けるようになったから?

ってか、勢い余ってる気が。

バックアップするだけのスクリプトに似つかわしくない画面。

情報表示に合わせて、色を付けるようにしたんですが、これ、ターミナルソフトによって全然色味が違うんですね。

image

左がWindowsターミナル、右がTeraTerm(いずれもデフォルト設定)

TeraTermの方が、純粋な色味に見えます。

Windowsターミナルの黄色は、もうベージュ、薄い茶色になってます。

全然違う。

image

Windowsターミナルの色味はここの選択次第って事か。

(;´∀`)

vintage辺りを選択すると、teratermの色味と同じ感じになります。

なるほど、今まで気にしてませんでしたが、ここでいうテーマってのは、ANSIカラーの基本16色の色を変えただけ?って事のようだ。

image

こちらは、VSCode内のターミナルの様子ですが、文字色を見ると分かります。

背景色に合わせて、文字自身の色が自動で切り替わってます。白っぽくなってたり、黒くなってたり。

※文字色は、デフォ色ANSI39

※ANSIカラーのデフォ色だったら、自動で背景色見て動作するようにしてる?とか

この辺の実装は流石というか、何を勝手な真似を・・と思う方も、居ないかw

Windowsターミナルや、TeraTermではこんな動作はしません。

Bashスクリプト系の情報は、探せば先人達の記事が沢山ヒットするので、非常に助かっております。

レガシーで古臭い、良く言えば保守的で、どんな古い情報やコードでも、それが丸々、現世でも活かせるという素晴らしい環境。某マイ◯ロソフト界隈のように、とっ散らかったサポート終了放置世界とは、雲泥であります。

コマンドのヘルプを見ながら、動作を確認しつつ、コツコツ進めております。

追記:いまさら気付く配列の悪魔

image

とっても、いまさら感が凄いんですが、Bashでは配列や連想配列も扱えるという事でコードを”普通に思い付きのまんま”書いてましたが。

何か挙動がおかしい??時はままあれど・・

ヽ(*゚∀゚*)ノま、ええか

的に、深く考えてなかったんですが、やっぱ、壁にぶち当たるもんです。

ここで、配列周りの仕様をちゃんと再確認してみる。

ほぅ・・なるほど。

配列っぽく使えるというのが正解のようで、変数参照の際は明示的に「これ配列ですからッ!」と教えてあげないと駄目。

関数への配列渡しは、基本不可能と考えた方が良い、という事。

(;´Д`)薄々は思ってたけど、やっぱそうなのか

関数は普通のシェルコマンドのように使える訳で、・・つー事は、コマンドライン上で配列との区別、書き様がない訳です。

function hoge() { ………….}

hoge “123 454 324 567 456” ← 文字列なのか配列なのか、分かるはずも無い

declare –pとすると、変数一覧が表示されるのですが、関数内では、確かに、型定義が"–“(未定)となってるのが分かる。

一方、declareでの変数宣言なんかも調べてみる。

変数のスコープや型?なんかも、情報を保持しているように見えるが・・。

じゃこちらで、明示的に配列として宣言してみたら、どうなるか?

declare –a box=(123 456 789) ← 配列として宣言

だが、この変数を渡しても、特別な事はしてくれない。何も状況は変わらない。

(;´Д`)・・・

この辺で諦める人は、全部グローバル変数でええやん、所詮、小さなシェルスクリプトやしッ

(ノω・`)

・・とかに陥るんでしょうね。

解決法が無いわけではないようで、渡したい変数の名前を渡して、受け取った側で、参照するという方法。

function hoge() {
declare –n sansho=$1 ← 参照宣言:変数の名前を入れる
echo ${sansho} ← 以降、参照した値をイジれる
echo ${#sansho[@]} ← 配列として扱える
}

hoge “box” ← 変数の名前を渡す

これなら、しっかりアクセスできました。

もう、これしか無いと思って、配列(連想含め)を扱っていくしかないようです。

しかし、この辺の挙動、エラー出ずに一見動くから、見逃しがちなんですよ(要素1個の配列として動く)

しかも、for~do~doneは、これを希望通りの配列としてループ動作するから、タチが悪い。

※区切り文字(IFS)

あぅ、全部書き直しや。

(;´Д`) せっかくだし全部declareで丁寧に書き起こそうか

侮れませんシェルスクリプト。

追記:

公式文書なども読み漁りました。

(;´∀`)

local –n とも書けるらしい。

上記の参照アクセスは、namerefと言われる機能で、Bash5かららしく最近出来たものらしい(現在の最新5.2.21)

プログラミング言語では当たり前過ぎるシロモノだけに、ちょいと驚いた

declare –n が出来るなら、その逆は出来ないんだろうか?・・

出来そうじゃないですか?

nameref変数の参照先の変数名を取得する方法です。

・・・と調べてみたが、一向に見当たりません。

ありそうなんだけども。

declare –p (変数名) で取得する事は出来ますが、分解して取得しなきゃいけない訳で、もっとスマートな方法がありそうな気がするんだけども。

なんで、こんなニッチな事を調べてるかというと。

配列渡し(ref)を、関数から、さらに関数へと渡す際に、泥臭い手間が掛かっちゃう訳です。

image

ターミナル越しでUbuntu Linux PC(Core i3 6100U)で作業してましたが、意味なく非効率な事をしてた事に気づき(今ッ?)

WSLを導入して、ローカル作業に切り替え(Core Ultra 135H)

マウスを使えるのよwこれ便利(え?)

最初からヤれよと(こんな長丁場になるとは想定してへんかったんよ)

そういえば、一度だけ、Bashスクリプトが変な挙動になりました。

エラー発生箇所がまったく意味不明な場所やコードを指してて、直しても、一向に変化が無い。1時間位、なんだかんだしても、変化無し。

途中、数分離席したのが原因かと思い、ターミナルを閉じて、再接続したら、治りました。

いままで同じような作業を、1-2ヶ月続けて来たのに、こんなの初めてです。

追記:

image

今のところ、こんな感じに落ち着きました。

自分のルールで、_refという変数に、名前だけ控えておいて。

利用の際は、別途declare -nしてと。

この関数から、さらに引き継いで関数へ渡していく場合は、_refを渡してます。

ローカル関係無く、変数名全てに、アンダースコア"_"付けてるんですが、エラー時、トラップして変数中身表示させてます(デバッグ用に)

この時、余計なものを省くルールとして、このアンダースコアを条件にしてます。

(;´∀`)

image

環境変数やら余計なものを、省いて、変数一覧も一緒に出してる。便利

$3 =~ ^_[[:alnum:]]+

これで判定してます。

しかし、以下の

while ~ done < <(declare -p)

この、whileへのリダイレクト、書き方は未だに理解できません。なんで真ん中に空白が無いと駄目なのか。

(;´Д`)

追記:おざなり過ぎだったBash

image

(上:固定幅フォントで崩れないAAを探してた)注:GW期間

今まで、基本を知らずシェル触ってきてたんだと思い知らされながらの作業です。

何か一つ触るたびに、新しい発見(気づき)に遭遇します。

テストしてみて「ほぉ・・」と。

(;´Д`)

※だから、一向に終わらない

(恥ずかしながら)、以下のような場合、スクリプトに、どんな感じに渡されるのか?

./test.sh ./hoge*

“./hoge*”という文字列が渡る訳では無い、というのは、なんとなく分かってましたが。

じゃ、全部展開されてんの??・・と

< ;`Д´> !!

調べればいいやん、と(すぐ実行に移せるのはシェルの便利なとこ)

“hoge1.txt” “hoge2.txt” “hoge3.txt”

こんな感じで、ヒットする分だけ、配列状態で入力されてました。

普段使ってるシェルコマンドで、よくワイルドカードを使いますが、彼らコマンドの中も同様って訳ですよ。

いま作ってるのは、バックアップ(+余計な事)をするだけのシンプルな物ですが、解凍も(同じコマンドで)やれたら便利だな、と思って、ここら辺も組み込んでる最中のところでした。

しかし、2025年ですけど、新鮮な体験ばかりですw

(;´∀`)

最近の疑問:マルチバイト文字の表示幅って、どーやって調べんの?

最近の発見:"yes"とかいう謎の標準コマンド

image

只今の記録:890行

※お、nameref用に書き換えてるぞ

追記:謎が一つづつ解決true/false

もう、さすがにデバッグしつつな作業が続いております。

ここで、今までしっかり仕様を確認していなかった事実が判明してしまいます。

_flag=true

if ${_flag}; then

 (なんかの処理)

fi

こんな基本的な判断とか、普通に書きますよ。

[ ${_flag} ] && (なんかの処理)

とか綺麗にも書けますよ。

_flagには、Boolean値が入ってるよねぇ、と体深くに刻み込まれた経験が自然の真理として無防備にそう思い込んでる訳ですよ。

このままでも普通に動いてくれてるんですが、実際にはダメダメで、判断式が複雑な時に、なんだか変な挙動に悩んでました。

ある時、ふっと、思いました。

あれ?このtrueって?何者??」・・と

(;´Д`)

/usr/bin/true (0が戻り値)

/usr/bin/false (1が戻り値)

あ・・・そういう事ね。

普通にコマンドでしたぁ。

ヽ( ;´Д`)ノ

コマンドなので、その出力で if は普通に動作しますが、Boolean値だと思って書いてると、謎な動作になってしまいます。

_flag=true

そもそも、この書き方が誤ってます。

”true”が入ってるだけ。

if [ ${_flag} ]; then

・・と書いた場合、

if [ true ]; then

として、展開される訳ですよ。

これ、”true”という文字列として評価されてしまってるんです。

なので、”false”でも、同様にTRUE判定になってしまう。

どーしても書きたいなら、こう書かなきゃいけない。コマンドだから・・

if [ $(true) ]; then

または、こう。展開後のコマンド実行結果が評価される。

if ${_flag}; then

${_flag} &&

やっと、謎の一つが解けた・・。

(;´Д`) ばっしゅたんカワユス(←極度の変態)

只今の記録:982行

追記:動作テストにも罠test

テスト用のターミナルを横に置いて、テストしながらコードを書いてるんですが、この時の罠(多分、俺くらい)

test
echo $?

function test() {
  return 0
}

このコード、何でか”1”(エラー)が表示されます。

return 0 が効いてないんですよ。なぜぇ??

賢明な方なら、すぐ察しますよね。。。

(;´Д`)

test関数がまだ定義されて無い段階で、testを呼び出してる。

ってか、testという標準コマンドが存在している(なのでエラー無し)

test を引数無しで実行すると、1(エラー)が帰る。

・・・という事です。

そもそもが、関数名に既存コマンド名を使っちゃいけない。

ヽ( ;´Д`)ノ

image

/bin(=/usr/bin) の中身です。

if [ 4545 –eq ${_doing:-1919} ]; then

IF文なんかの条件式で多用される”[ ]”ですが、”[“ の後に空白が必要!と言われてる訳が分かります。

上写真を見ると一目瞭然。

“[“自体がコマンド名なのです。

だから、空白で開けて引数になる条件式を書いてる訳なんですね。

IF文が評価してるのは、”[“コマンドの戻り値。

追記:そろそろ公開?

image

動作テストも、あと少しとなりました。

今年のGWって・・、明日で終わりらしい。

(;´Д`)

ドキュメント(—help)もしっかり整備して、なるべく敷居が低くなるように配慮したつもり。

しかし、せっかく覚えたBashスクリプトですが、なんだか数日触らなくなったら、忘れそうw

只今の記録:1268行

追記:動作確認

image

動作確認しまくっとります。

当てずっぽで書いてたコマンドが、案外、動かないというw

(;´∀`)

がっつりモードで、デバッグしてますよw

今まで適当に使ってたコマンドとかも、ちゃんとドキュメント読んで、一個づつ、ちゃんと書いて動作確認して、ってやってます。

smbclientとか、¥じゃなくて、/で書いても良いんだ、とか。色んな発見があって、勉強になる。

あと、引数のパターンの違いとかね、コマンドによって全然違う、ssh系は、左から右に流れで書ける。

HTTP越しのアップロードバックアップなんだが、、さて、どうデバッグするか。。

(;´Д`)

現在の記録:1282行

追記:( ^ω^)おっおっおっ

image

おっ、Bashでアクションゲーム作れるやん(←完全な脱線状態)

(;´∀`)・・・

ちゃ、、ちゃんとデバッグは進行中で御座います。

適当に、exitとか書いてた部分を、returnに変えて、ちゃんとフロー制御するようにして綺麗に流れるコードに変えました。

レポートをする機能があるので、ここでエラーコードやらを投げてます。

$?、これ、ただのエラーコードなので、これを人間が読める形にするか、どうかで悩んでる所。

image

さて、on_finally()の冒頭の部分なのですが、exit時に必ず呼ばれる関数になってます。

_result に、exitのエラーコードを格納してるんですが。

これが、なぜか、常に0なのですよ。

こんな、くだらない事に、数十分も費やしましたよ。

(´;ω;`)

プログラム噛じった人ほど、陥りやすいバッシュ罠で御座いました。

image

主要な部分に入る前に、環境や設定のチェックをする部分を追加。

必要なコマンドが導入されてない場合もあるでしょうし、これで、環境作りや設定もヤりやすくなるでしょう。多分

しかし、かれこれ数ヶ月程、Bashスクリプトを書いてきた訳ですが、最初の頃に書いた部分とか、ほとんど理解せず書いてたんで、これらを直し直し、そしたら、また新しい事覚えるんで、また書き直しと。。これ、終わるんかw

もう、だいぶ落ち着きましたけども。

(;´∀`)

只今の記録:1357行

2025年4月4日プライベートbash,linux,script,ubuntu,vi

Posted by nabe