Powershellでは、次のことを行うことに慣れています。
> $python_files = get-childitem *.py
> echo $python_files[0]
get-childitem
2番目のコマンドを使用すると、配列に似たオブジェクトが返されるため、最初のファイルを抽出できます。
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...)
。これは別のシナリオであり、単語の区切りが関連しているためです。)
find
Bashから配列の出力を読み取るには、readarray
プロセス置換(これ<(...)
)を使用できます。
readarray -d '' -t files < <(find ... -print0)
printf '%s\n' "Third element of array is '${files[2]}'"
-print0
find
NULバイトで出力の各ファイル名を終了するように指示します。これはファイル名には現れない唯一のバイトなので、明示的なシリアライゼーションで機能します。 NULを区切り文字として期待するように指示-d ''
します。readarray
配列インデックスは次から始まります。若いBashから(参照http://mywiki.wooledge.org/BashGuide/Arrays)。
(移植性に関して:すべてのシェルがアレイをサポートしているわけではなく、zshはサポートしていますが、少し異なる動作をします。標準ではありませんが、広くサポートされてい-print0
ます。)
または、シェルglobと一致するファイルのリストが必要な場合:
files=( *.py )
(一致するファイルがない場合、bash
このオプションを設定しないと、呼び出された要素が取得されます。)*.py
nullglob
globstar
ここでは、またはdotglob
他のオプションを使用できますがextglob
、使用可能なオプションはもちろんシェルによって異なり、提供されたfind
オプションとは異なります。