bashシェルを使用してコマンドを複数回実行する方法は?


153

コマンド(例えばps aux|grep someprocess)をn回実行する方法はありますか?

何かのようなもの:

run -n 10  'ps aux|grep someprocess'

インタラクティブに使用したいので、スクリプトを投稿しないでください。

更新:私がこれを求めている理由は、私は多くのマシンで作業しており、すべてのマシンで同じ機能を得るためにすべての適応スクリプトをすべてのボックスにインポートしたくないからです。


回答:


197

これにはBourneシェルforループが設計されたもののごく一部であるため、このためのコマンドまたはシェル組み込みは存在しないと思います。

まず、ダミーforループを使用できます。

for i in `seq 10`; do command; done

または、JimBの提案に従って、シーケンスを生成するためにBashビルトインを使用します:

for i in {1..10}; do command; done

これは、command毎回実行を10回繰り返します- ;またはで区切られたパイプまたは一連のコマンド&&です。$i変数を使用して、どの反復にいるのかを知ることができます。

このワンライナーをスクリプトとみなすため、不特定の(ただしおそらく有効な)理由で望ましくない場合は、コマンドとして実装できます。

#function run
run() {
    number=$1
    shift
    for i in `seq $number`; do
      $@
    done
}

使用法:

run 10 command

例:

run 5 echo 'Hello World!'

16
@mahatmanich、ループはスクリプトではありません。対話式端末でfor ...を使用することを妨げるものは何もありません。
ゾレダチェ

3
さて、上のワンライナーはそれを行うための標準的な方法の一種であり、かなり簡単です。なぜあなたにとって良くないのですか?たぶん、あなたは間違った質問をしているのでしょうか?何度も繰り返したいスクリプトやアクションの主な目標は何ですか?別の方法で問題を解決すれば、より良い解決策があるかもしれません。
パトコスチャバ

6
@mahatmanich - for である内蔵の反復のためにbashが。
JimB

3
@Eduardo Ivanec - FYI、bashは組み込まれている範囲のようにseq{1..10}
JimB

1
組み込みのブラケットシーケンスは変数置換をサポートしていないようです(stackoverflow.com/a/3737773/713554を参照)。ただし、交換した.bashrc場合、指定した関数{1..$number} は配置されたときに完全に機能します`seq $number`
レオ

29

ps aux | grep someprocessプログラムの変更を一定時間監視したいようです。エドゥアルドはあなたの質問に正確に答える答えを出しましたが、別の方法がありますwatch::

watch 'ps aux | grep someprocess'

シェルがコマンドを「run watch ps aux」と解釈して結果をパイプすることを避けるために、コマンドを単一引用符で囲んでいることに注意してくださいgrep someprocess。前のコマンドを実行する別の方法は次のとおりです。

watch ps aux \| grep someprocess

デフォルトでは、watch2秒ごとに更新されますが、-nオプションを使用して変更できます。たとえば、1秒の間隔が必要な場合:

watch -n 1 'ps aux | grep someprocess'

21

ただの楽しみのために

pgrep ssh ;!!;!!;!!;!!;!!;!!

誰かこれを説明してもらえますか?とても興味深く見えます。
ダニエルバルタノフ14

4
; は単なるコマンドセパレータです。!! bashで最後のコマンドを再生します。したがって、これは「pgrep ssh」を実行してから6回再生します。
ピョートルクキエルカ14

それは有益ですが、非常に直感的ではありません。ワンライナーforが最良の方法のようです。とにかく答えてくれてありがとう。
erm3nda

1
cmd ;!!1行で、現在の行の前に入力したコマンドを繰り返すだけではありませんか?2つの個別のhistoryエントリである必要があります。
ジョエルプラ

で置き換え;&&、最初の障害で停止します。
user881300

16

前の返信と同様ですが、forループは不要です。

seq 10 | xargs -I -- echo "hello"

引数またはオプションなしでseqの出力をxargsにパイプする


2
これにより、1回実行されecho "hello" 1 2 3 4 5 6 7 8 9 10ます。xargsは-n 1、入力ごとに1つのプロセス(数値)と-P 10並列実行(10並列プロセス)で実行する必要があります。で終わるseq 10 | xargs -n 1 -P 10 echo
アレクサンダークリメチェック

16

これを試して:

yes ls | head -n5 | bash

これには、コマンドをサブシェルで実行する必要がありますが、パフォーマンスがわずかに低下します。YMMV。基本的に、文字列「ls」をN回繰り返す「yes」コマンドを取得します。一方、「head -n5」は5回の繰り返しでループを終了しました。最後のパイプは、選択したシェルにコマンドを送信します。

ちなみにcsh-likeシェルには組み込みrepeatコマンドがあります。それを使用して、bashサブシェルでコマンドを実行できます!


5

POSIXの方法

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04_01

x=10
while [ $x -gt 0 ]; do
    command
    x=$(($x-1))
done

もちろん、1つのライナーにすることができます:

x=10; while [ $x -gt 0 ]; do command; x=$(($x-1)); done

最も移植性の高い方法であるため、プログラムをインストールする可能性が低くなります。

以下は移植性が低くなります。

  • ブレース展開{1..10}:bash固有、引数が大きい場合は巨大な行を生成します
  • seq:GNU
  • yes:GNU

そして、移植性に飽きたら、GNUを検討してparallelください:

sudo apt-get install parallel
seq 100 | parallel echo {}

コマンドを並行して実行し、多くのクールなオプションがあります。

参照:https : //stackoverflow.com/questions/169511/how-do-i-iterate-over-a-range-of-numbers-defined-by-variables-in-bash


GNU Parallelは非常に移植性が高いように構築されています。sh, zsh, ksh、およびbashほとんどすべてのプラットフォームで十分にサポートされています。csh, tcsh, fishいくつかのサポートがあります。使用parallel --embedすると、GNU Parallelがインストールされていない別のシステムに簡単に移動できるスクリプトを作成することもできます。
オレ丹下

2

上記の@ eduardo-ivanecのrun関数のフィッシュシェル実装

function run
  set number $argv[1]
  for i in (seq $number)
    eval $argv[2..-1]
  end
end

0

それは「ウォッチ」になります-procpsを使用するほぼすべてのUNIXシステムの一部である必要があります

システムのfsの変化や興味深い動きを見ることができます。例えば、

watch "df -hP | grep /tmp" 

引数としてコマンドを入力するだけです(を参照man watch


時計との答えは...右の下記を参照してください...すでにある
mahatmanich

0

macOSでは、repeatコマンドを使用できます。

repeat 10 ps aux | grep someprocess
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.