2017-09-18 9 views
2

プログラムに入力として与えられたファイルを処理するプログラムを作成しようとしていますが、値渡しとパラメータ経由での両方のパイプラインをサポートします。パラメータとstdinを同じ変数に読み込み、空白を残す

find . -type f | program -dvs 

または多分あなたは同じことをやってみたいが、内のすべてのファイルについて:

例えば、1はフラグを使用して、現在のディレクトリ内のすべてのファイル上でプログラムを実行したい場合があります-dvs $ FILES_TO_CHECK変数:

echo "$FILES_TO_CHECK" | program -dvs 

これは私がこれまで持っているコードです:と

tmp1() { 
    local in=("[email protected]") 

    if read -t 0 -u 0; then 
    local pipe="" 
    read -d '' -u 0 pipe 
    in+=(${pipe}) 
    fi 

    local param 
    for param in "${!in[@]}"; do 
    echo "'$param' => '${in[$param]}'" 
    done 
} 

テスト:上記

echo "cba" "bca" "cba abc" | tmp1 "a" "b" "c" "abc" "abc cba" 
echo; echo; echo 
find . -type f 
find . -type f | tmp1 "a" "b" "c" "abc" "abc cba" 

は、次のように出力できます:

'0' => 'a' 
'1' => 'b' 
'2' => 'c' 
'3' => 'abc' 
'4' => 'abc cba' 
'5' => 'cba' 
'6' => 'bca' 
'7' => 'cba' 
'8' => 'abc' 



./1 
./2 
./3 
'0' => 'a' 
'1' => 'b' 
'2' => 'c' 
'3' => 'abc' 
'4' => 'abc cba' 

近いですが、私は望んでいない、まさに:

'0' => 'a' 
'1' => 'b' 
'2' => 'c' 
'3' => 'abc' 
'4' => 'abc cba' 
'5' => 'cba' 
'6' => 'bca' 
'7' => 'cba abc' 



./1 
./2 
./3 
'0' => 'a' 
'1' => 'b' 
'2' => 'c' 
'3' => 'abc' 
'4' => 'abc cba' 
'5' => './1' 
'6' => './2' 
'7' => './3' 

私はトップケースわからないんだけど(パイプされた値からスペース文字を維持する)ことはまったく可能ですが、そうであればどうしますか?
2番目のケースでは、検索結果がプログラムによって読み取られないのはなぜですか?

編集:これを行うための他のより良い方法がある場合は、私もすべての耳です。 実際のループは後ではるかに複雑になるので、私はパラメータ用に1つのループを作成し、パイプされた値用にもう1つのループを作成しないでください。

+0

stdinから条件付きで読むために 'read -t 0 'を使うのはアンチパターンです。 UNIXコマンドは予測可能でなければなりません。常にstdinから読み込むか、決して実行しないでください。私はそれを単純に保ち、コマンドラインだけを解析することを勧めます。出力を引数に変換したい場合、 'xargs'を使うことができます。 –

+0

'xargs'を使うと' xargs:tmp1:No such file or directory'という出力が出ます。私がこれを得ることができたら、私はあなたに同意するでしょう。 – TheNamlessGuy

答えて

1

tmpは標準入力からヌル区切りのレコードを読み取りますが、テストでは空白文字で区切られた文字列が送信されています。

printf '%s\0' "cba" "bca" "cba abc" | tmp1 "a" "b" "c" "abc" "abc cba" 
find . -type f -print0 | tmp1 ... 

とテスト(これは、出力ファイル名を、NULLで終了することができますfindのバージョンを前提としています。)tmpインサイド

は、あなたがして、同様$pipeを引用し、それぞれのファイルを取得するために入力をループする必要があります配列に追加

if read -t 0 -u 0; then 
    local pipe="" 
    while read -d '' pipe; do 
    in+=("$pipe") 
    done 
fi 

あなたがbash 4.4以降を使用している場合は、代わりにループのreadarrayを使用することができます。

readarray -t -d '' -O "${#in[@]}" in 
+0

if文をwhileループに変更して、区切り文字を改行に変更し、代わりにそれを区切るようにユーザーに依頼するとします。 空白の有無をデータで保持することを望んでいました配管後の入力フラグの一部だったが、それは不可能だと思う。 find-issueに関するご意見はありますか? – TheNamlessGuy

+0

ヌル文字は、ファイル名に使用できない唯一の文字であるため、ファイル名を区切るための唯一の安全なオプションです。 – chepner

+1

'find'がすぐに何も出力しないのであれば? 'read -t 0'は非常に脆弱です。 –

関連する問題