web-dev-qa-db-ja.com

while条件でパイプを使用するにはどうすればよいですか?

私はgrepが私が書くことができるものを見つけたり見つけなかったりしながらループしたい:

while grep 'matches' inLogFile.txt
do
  echo good.
  sleep 10
done

または

while grep -v 'notHereYet' inLogFile.txt
do
  sleep 2
done
echo -e '\a'Yo! It is here now.

対話型のシェルプロンプトでこれらを入力しています。

だから、ボリュームが実際にマウントされたときのdfを繰り返しチェックしたかった。

while df | grep -v '/toBeMounted'
do
  sleep 2
done
echo -e '\a'Hey, I think you wanted to know that /toBeMounted is available finally.

パイプを条件にグループ化する方法がわかりません。

私は次のようなことができることを知っています:

while [ -z "$(df|grep '/toBeMounted')" ]
do
  sleep 2
done
echo -e '\a'Okay that is finally present now.

それでも、文字列比較の代わりに終了値を使用してそれを行う方法があるべきだと感じています。

4
dlamblin

ロジックを正しくするには、わずかな変更が必要です。つかいます:

while ! df | grep '/toBeMounted'
do
  sleep 2
done
echo -e '\a'Hey, I think you wanted to know that /toBeMounted is available finally.

討論

質問の対応するコードは次のとおりです。

while df | grep -v '/toBeMounted'

パイプラインの終了コードは、パイプラインの最後のコマンドの終了コードです。少なくとも1行の入力がgrep -v '/toBeMounted'と一致しない場合、/toBeMountedはtrue(code = 0)を返します。したがって、これは/toBeMounted以外にマウントされているものがあるかどうかをテストします。 これはあなたが探しているものではありません。

dfおよびgrepを使用して/toBeMountedがマウントされているかどうかをテストするには、

df | grep '/toBeMounted'

/toBeMountedがマウントされている場合、これはtrueを返します。実際に必要なのはこれの否定です:/toBeMountedがマウントされていない場合にtrueになる条件が必要です。そのためには、!で示される否定を使用するだけです。

! df | grep '/toBeMounted'

そして、これが上記のコードで使用しているものです。

ドキュメンテーション

Bashマニュアル から:

Pipefailオプションが有効になっていない限り、パイプラインの戻りステータスは最後のコマンドの終了ステータスです。 pipefailが有効な場合、パイプラインの戻りステータスは、ゼロ以外のステータスで終了する最後の(右端の)コマンドの値、またはすべてのコマンドが正常に終了した場合はゼロです。予約語!がパイプラインの前にある場合、そのパイプラインの終了ステータスは、上記の終了ステータスの論理否定です。シェルは、パイプライン内のすべてのコマンドが終了するのを待ってから値を返します。

8
John1024

dfgrepと一緒に使用しているという事実は、特定のディレクトリにデバイスがマウントされるまで、つまりリストにあるかどうかにかかわらず、dfの出力をフィルタリングしていることを示しています。

リストをフィルタリングする代わりに、目的のディレクトリに焦点を合わせます。幸運なことに、ユーティリティmountpointを使用すると、まさにそれを実行でき、そのコマンドの終了ステータスを処理できます。このことを考慮:

$ mountpoint  /mnt/HDD/                                                        
/mnt/HDD/ is a mountpoint
$ echo $?
0
$ mountpoint  ~                                                                
/home/xieerqi is not a mountpoint
$ echo $?
1

したがって、スクリプトは次のように書き換えることができます。

while ! mountput /toBeMounted > /dev/null
do
   sleep 3
done
echo "Yup, /toBeMounted got mounted!"

自分のディスクで実行するサンプル:

$ while ! mountpoint /mnt/HDD > /dev/null
> do 
>     echo "Waiting"
>     sleep 1
> done && echo "/mnt/HDD is mounted"
Waiting
Waiting
Waiting
Waiting
Waiting
/mnt/HDD is mounted

補足として、たとえばpythonでmountpointコマンドの独自のバージョンをかなり簡単に実装できます。

#!/usr/bin/env python3
from os import path
import sys

def main():

    if not sys.argv[1]:
       print('Missing a path')
       sys.exit(1)

    full_path = path.realpath(sys.argv[1])
    with open('/proc/self/mounts') as mounts:
       print
       for line in mounts:
           if full_path in line:
              print(full_path,' is mountpoint')
              sys.exit(0)
    print(full_path,' is not a mountpoint')
    sys.exit(1)

if __== '__main__':
    main()

サンプル実行:

$ python3 ./is_mountpoint.py /mnt/HDD                                          
/mnt/HDD  is mountpoint
$ python3 ./is_mountpoint.py ~                                                 
/home/xieerqi  is not a mountpoint
4