目的
- 複数のファイルをbashの配列に入れてファイル名を取り出す方法です。
- 背景:複数の処理を行っていて、例えば巨大なMP3を時間分割して、それをWAVに変換して、WAVからFFTに変換して、そのFFTを元にスペクトログラムのpngに変換してと、中間ファイルがいっぱいできます。この時に処理がどこまで進んだのかを別のプロセスからチェックしたくなりました。そのため拡張子毎のファイル数を勘定しようと思いました。また、このリストをJavascriptに渡したいので配列として取り出したかったです。
- シェルスクリプトらしさにこだわる議論は下記にありますが、動くコードこそ正しいとも思います。適材適所で。
参考
確かめた環境
- centOS7/bash 4.2
- MacOS Darwin Kernel Version 19.4/bash: 5.0
できたコード
list_png=($(find . -name "*.png"))
# ファイルがあると分かっているときはこちらでもいいです。
list_png=($(ls -1 "*.png"))
説明
- ポイントはコマンドを実行する
$()
を()
で包むだけです。 -
()
に囲むことで配列に入れられます。これに気がつくまでに30分悩みましたのでお裾分けです。 -
ls -1
はファイルをそれぞれ1行に出力するオプションです。ls
はソートして出力するのでfind
よりも遅いですが、ソートさせない場合にはls -U
とかすればいい様です。
検証
$ ls -1 190427_18*png
190427_180000-180400.png
190427_180400-180800.png
...
190427_185600-190000.png
$ list_png=($(ls -1 190427_18*png))
# 確認します
$ echo ${list_png[*]}
190427_180000-180400.png 190427_180400-180800.png 190427_180800-181200.png 190427_181200-181600.png 190427_181600-182000.png 190427_182000-182400.png 190427_182400-182800.png 190427_182800-183200.png 190427_183200-183600.png 190427_183600-184000.png 190427_184000-184400.png 190427_184400-184800.png 190427_184800-185200.png 190427_185200-185600.png 190427_185600-190000.png
# ファイル数を確認します
$ echo ${#list_png[*]}
15
# 勿論こっちがシェル的
$ ls -1 190427_18*png | wc -l
15
# ファイル名を取り出します。配列は0から始まります。
$ echo ${list_png[0]}
190427_180000-180400.png
$ echo ${list_png[1]}
190427_180400-180800.png
# ブレースがないと一番最初のファイルだけ表示されました。
$ echo $list_png
190427_180000-180400.png
# 配列の最大値は個数-1です
$ echo ${list_png[14]}
190427_185600-190000.png
# 個数の値を入れても空を出力しますがエラーは起こっていないです。
$ echo ${list_png[15]}
$ echo $?
0
# lsはファイルがないとエラーが起こります。set -xの設定していると止まってしまいますのでfindを使う方がいいです。
$ ls *AAA
ls: %Aにアクセスできません:そのようなファイルやディレクトリがありません
$ echo $?
2
# findは異常終了エラーを返しません
$ find . -name "*AAA"
$
$ echo $?
0
どなたのお役に立てれば嬉しいです。