[解決済み] Bashでfindコマンドの結果を配列として保存するには?
質問
の結果を保存しようとしています。
find
の結果を配列として保存しようとしています。
以下は私のコードです。
#!/bin/bash
echo "input : "
read input
echo "searching file with this pattern '${input}' under present directory"
array=`find . -name ${input}`
len=${#array[*]}
echo "found : ${len}"
i=0
while [ $i -lt $len ]
do
echo ${array[$i]}
let i++
done
カレントディレクトリの下に2つの.txtファイルを取得します。
そこで、私は、'2' を
${len}
. しかし、それは1を表示します。
その理由は
find
の結果を1つの要素として受け取ってしまうからです。
どうしたら直せますか?
P.S
StackOverFlowで似たような問題でいくつかの解決策を見つけました。しかし、彼らは少し異なっているので、私は私のケースに適用することはできません。私はループの前に結果を変数に格納する必要があります。本当にありがとうございます。
どのように解決するのですか?
Linux ユーザーのための 2020 年アップデート。
Linux であればおそらくそうであるように、最新バージョンの bash (4.4-alpha またはそれ以上) を使用している場合は Benjamin W. の回答 .
もしあなたがMac OSを使っていて、最後に確認したときはまだbash 3.2を使っていた、あるいはそれ以外の古いbashを使っているなら、次のセクションに進みます。
bash 4.3 またはそれ以前のバージョンに対する回答
の出力を取得するための1つの解決策です。
find
の出力を
bash
の配列に変換します。
array=()
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done < <(find . -name "${input}" -print0)
一般に、ファイル名には空白や改行などのスクリプトにとって好ましくない文字が含まれることがあるため、これは厄介なことです。 唯一の方法は
find
を使用し、ファイル名を安全に分離する唯一の方法は
-print0
を使うことです。これはファイル名をヌル文字で区切って表示します。 これは、もしbashの
readarray
/
mapfile
のような関数がヌル文字列をサポートしていましたが、そうではありません。 Bashの
read
がそうで、それが上のループにつながるのです。
[この回答は2014年に書かれたものです。 最近のバージョンのbashをお持ちの方は、以下のアップデートをご覧ください] 。
どのように動作するか
-
最初の行では、空の配列を作成しています。
array=()
-
を実行するたびに
read
ステートメントが実行されるたびに、ヌル区切りのファイル名が標準入力から読み込まれます。 その際-r
オプションはread
にバックスラッシュを残します。 このオプションは-d $'\0'
はread
に、入力がヌル区切りになることを伝えます。 名前を省略しているのでread
を省略すると、シェルは入力をデフォルトの名前にします。REPLY
. -
は
array+=("$REPLY")
ステートメントは新しいファイル名を配列に追加します。array
. -
最後の行は、リダイレクトとコマンド置換を組み合わせて、出力に
find
の標準入力に対してwhile
ループの標準入力に追加します。
なぜプロセス代替を使うのか?
もしプロセス代入を使わなければ、ループは次のように書くことができます。
array=()
find . -name "${input}" -print0 >tmpfile
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done <tmpfile
rm -f tmpfile
上記の出力では
find
の出力は一時ファイルに保存され、そのファイルは while ループの標準入力として使用されます。 プロセス代替の考え方は、このような一時ファイルを不要にすることです。 そのため、代わりに
while
ループがその標準入力を
tmpfile
から標準入力を得るようにすることができます。
<(find . -name ${input} -print0)
.
プロセス置換は広く有用である。 多くの場所で、コマンドが
を読む
をファイルから読み込みたい場合、プロセス置換を指定することができます。
<(...)
を指定することができます。 類似の形式があります。
>(...)
という形式もあり、これはファイル名の代わりに使うことができます。
を書く
をファイルへ書き込むことができます。
配列と同様、プロセス置換はbashや他の先進的なシェルの機能である。 POSIX標準の一部ではありません。
代替: lastpipe
必要であれば
lastpipe
をプロセス置換の代わりに使うことができます(脱帽。
シーザー
):
set +m
shopt -s lastpipe
array=()
find . -name "${input}" -print0 | while IFS= read -r -d $'\0'; do array+=("$REPLY"); done; declare -p array
shopt -s lastpipe
はパイプラインの最後のコマンドを(バックグラウンドではなく)現在のシェルで実行するようbashに指示します。 この方法では
array
はパイプラインが完了した後も存在し続けます。 なぜなら
lastpipe
が有効になるのはジョブ制御がオフの場合だけなので、パイプラインの終了後に
set +m
. (コマンドラインとは対照的に、スクリプトでは、ジョブ制御はデフォルトでオフになっています)。
補足説明
以下のコマンドは、シェル配列ではなく、シェル変数を作成します。
array=`find . -name "${input}"`
もし、配列を作りたかったら、findの出力に括弧をつける必要があります。 だから、素朴に、1つはできた。
array=(`find . -name "${input}"`) # don't do this
の結果に対してシェルが単語分割を行うことが問題です。
find
の結果に対して単語分割を行うため、配列の要素が望みのものになることが保証されないということです。
2019年更新
バージョン4.4-alphaから、bashが
-d
オプションが追加され、上記のループは必要なくなりました。 代わりに、1つは使用することができます。
mapfile -d $'\0' array < <(find . -name "${input}" -print0)
これについての詳細は、以下を参照してください (そしてアップボートしてください)。 Benjamin W. さんの回答 .
関連
-
[解決済み] 配列から特定の項目を削除するにはどうすればよいですか?
-
[解決済み] Linuxで特定のテキストを含むすべてのファイルを検索するにはどうすればよいですか?
-
[解決済み] Bashスクリプトのソースディレクトリをスクリプト自体から取得するにはどうすればよいですか?
-
[解決済み] JavaScript で配列に値が含まれているかどうかを確認するにはどうすればよいですか?
-
[解決済み] Bashシェルスクリプトでディレクトリが存在するかどうかを確認するにはどうすればよいですか?
-
[解決済み] Bashで通常のファイルが存在しないかどうかを判断する方法を教えてください。
-
[解決済み] Bashで文字列変数を連結する方法
-
[解決済み] オブジェクトが配列であるかどうかを確認するにはどうすればよいですか?[重複]。
-
[解決済み] Bashスクリプトからプログラムが存在するかどうかを確認するにはどうすればよいですか?
-
[解決済み] Bashでコマンドライン引数を解析するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Verilogで1次元と2次元のバイト配列を宣言して使用するには?
-
[解決済み] MATLABで動的配列を作成する方法
-
[解決済み] Scala:Arrayに要素を追加する最良の方法は何ですか?
-
[解決済み] int (*p)[10]=s と int (*o)[5]=&s の違いは何ですか?
-
[解決済み] glVertex3fvとglVertex3fの相違点
-
[解決済み] GCCです。配列型に不完全な要素型がある
-
[解決済み] 最大単品販売利益
-
[解決済み] Postgres の配列の NOT
-
[解決済み] Angular 2とTypeScriptで2つのオブジェクト配列をマージする?
-
[解決済み] kotlinで空の配列を作成するには?