"find"コマンドが配列に似た要素を返さない場合、この問題を解決する方法

"find"コマンドが配列に似た要素を返さない場合、この問題を解決する方法

Powershellでは、次のことを行うことに慣れています。

> $python_files = get-childitem *.py
> echo $python_files[0]

get-childitem2番目のコマンドを使用すると、配列に似たオブジェクトが返されるため、最初のファイルを抽出できます。

Bashでは、次の内容がほぼ同じであることがわかります。

> test=$(find . -iname '*.py')

ところで、最初の項目を取得できなかったので、文字列のようなオブジェクトが返されるとecho $test[0]思いました。find

コマンドから最初の項目を取得する一般的な方法はありますかfind?汎用とはコマンドに依存しませんgrep

答え1

Bashでは、次の内容がほぼ同じであることがわかります。

test=$(find . -iname '*.py')

しかし、echo $test[0]最初の項目を取得できなかったため、findが文字列などのオブジェクトを返すとします。

一部の値では「おおよそ」です。実際、「おおよその」値は非常におおよそのものです。

パイプとコマンドの置換は、ファイルなどのオブジェクトであるコマンドの出力(標準出力、stdout)を読み取ることに依存します(もちろん、検索できません(ランダムアクセスなど))。これはバイトストリームです。次のようにシリアル化されない限り、データ構造の転送は許可されません。バイトシーケンス

あなたが望むのは、ファイル名を1行に1つずつ印刷するようにtest=$(find . -iname '*.py')要求しfind、シェルがそれを文字列として変数に読み込むようにすることですtest。変数には次の内容が含まれますhello.txt<newline>there.txt。これはある程度は大丈夫ですが、シェル配列ではないため、インデックスを作成できず、ファイル名に改行文字が含まれていると中断されます。 (また、ファイル名にスペースが含まれていると壊れますfor f in $(find...)。これは別のシナリオであり、単語の区切りが関連しているためです。)

findBashから配列の出力を読み取るには、readarrayプロセス置換(これ<(...))を使用できます。

readarray -d '' -t files < <(find ... -print0)
printf '%s\n' "Third element of array is '${files[2]}'"

-print0findNULバイトで出力の各ファイル名を終了するように指示します。これはファイル名には現れない唯一のバイトなので、明示的なシリアライゼーションで機能します。 NULを区切り文字として期待するように指示-d ''します。readarray配列インデックスは次から始まります。若いBashから(参照http://mywiki.wooledge.org/BashGuide/Arrays)。

(移植性に関して:すべてのシェルがアレイをサポートしているわけではなく、zshはサポートしていますが、少し異なる動作をします。標準ではありませんが、広くサポートされてい-print0ます。)

または、シェルglobと一致するファイルのリストが必要な場合:

files=( *.py )

(一致するファイルがない場合、bashこのオプションを設定しないと、呼び出された要素が取得されます。)*.pynullglob

globstarここでは、またはdotglob他のオプションを使用できますがextglob、使用可能なオプションはもちろんシェルによって異なり、提供されたfindオプションとは異なります。

関連情報