404エラーが発生した後に「wget」をどのように停止しますか?

404エラーが発生した後に「wget」をどのように停止しますか?

次のように中括弧拡張を使用すると、順番に番号付けされたwget画像を簡単に取得できます。

$ wget 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg'

番号付きの最初の10個の90.jpgファイルをインポート99.jpgし、100.jpg404: ファイルが見つかりません{00..200}エラー(私のサーバーには100個の画像しか保存されていません)。増やしてサーバーに多少の負担になることもあります。少なくとも問題があります)。

wget最初の404エラーが発生した後に停止する方法はありますか? (または他の理由でファイルが範囲内で失われる場合は、連続して2つの方が良いです。)答えには、中括弧拡張を使用する必要はありません。

答え1

ループに満足している場合:

for url in 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg'
do
    wget "$url" || break
done

wgetこれは失敗するまで拡張のすべてのURLに対して実行され、breakループを終了します。

連続して2回の失敗が予想されると、状況はより複雑になります。

for url in 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg'
do
    if wget "$url"
    then
        failed=
    elif [ "$failed" ]
    then
        break
    else
        failed=yes
    fi
done

&&使用して||少し縮小できますが、if本当に見苦しくなります。

wget私はこれを行うことが組み込まれていると信じていません。

答え2

この$?変数を使用してwgetの戻りコードを取得できます。ゼロ以外の場合はエラーが発生したことを意味し、しきい値に達するまでそれを計算してからループから外れることがあります。

こんな感じです。

#!/bin/bash

threshold=0
for x in {90..110}; do
    wget 'http://www.iqandreas.com/sample-images/100-100-color/'$x'.jpg'
    wgetreturn=$?
    if [[ $wgetreturn -ne 0 ]]; then
        threshold=$(($threshold+$wgetreturn))
        if [[ $threshold -eq 16 ]]; then
                break
        fi
    fi
done

forループは少し整理できますが、一般的なアイデアを得ることができます。

$threshold -eq 16停止する前に3回失敗するという意味に変更されました-eq 24。ただし、連続して2回ではなく、ループで2回失敗すると失敗します。

16sumを使用する理由24は、戻りコードの合計であるためです。 wgetはサーバーからエラーに対応する応答コードを受け取ると戻り
コードで応答するため、合計2つのエラーが発生します。816

失敗が連続して 2 回だけ発生した場合、停止するには、wget成功時にしきい値をリセットします (例: 戻りコードが 0 の場合)。


wget戻りコードのリストはここにあります。http://www.gnu.org/software/wget/manual/html_node/Exit-Status.html

答え3

終了コード/ステータスに焦点を当てたIMOは、いくつかのwgetユースケースではあまりにも素直である可能性があるため、ここではいくつかの詳細な決定とともにHTTPステータスコードも考慮されます。

wgetコマンドのHTTP応答ヘッダーを-S/--server-response印刷するためのフラグを提供します。そのヘッダーを抽出して作業できます。STDERR

#!/bin/bash

set -eu

error_max=2
error_count=0

urls=( 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg' )

for url in "${urls[@]}"; do
  set +e
  http_status=$( wget --server-response -c "$url" 2>&1 )
  exit_status=$?
  http_status=$( awk '/HTTP\//{ print $2 }' <<<"$http_status" | tail -n 1 )

  if (( http_status >= 400 )); then
    # Considering only HTTP Status errors
    case "$http_status" in
      # Define your actions for each 4XX Status Code below
      410) : Gone
        ;;
      416) : Requested Range Not Satisfiable
        error_count=0  # Reset error_count in case of `wget -c`
        ;;
      403) : Forbidden
        ;&
      404) : Not Found
        ;&
      *)     (( error_count++ ))
        ;;
    esac
  elif (( http_status >= 300 )); then
     # We're unlikely to reach here in case of 1XX, 3XX in $http_status
     # but ..
     exit_status=0
  elif (( http_status >= 200 )); then
     # 2XX in $http_status considered successful
     exit_status=0
  elif (( exit_status > 0 )); then

    # Where wget's exit status is one of
    # 1   Generic error code.
    # 2   Parse error 
    #     - when parsing command-line options, the .wgetrc or .netrc...
    # 3   File I/O error.
    # 4   Network failure.
    # 5   SSL verification failure.
    # 6   Username/password authentication failure.
    # 7   Protocol errors.

    (( error_count++ ))
  fi

  echo "$url -> http_status: $http_status, exit_status=$exit_status, error_count=$error_count" >&2

  if (( error_count >= error_max )); then
    echo "error_count $error_count >= $error_max, bailing out .." >&2
    exit "$exit_status"
  fi

done

答え4

私がうまく使用したのは

wget 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg' 2>&1 | grep -q 'ERROR 404: Not Found'

grep -q入力で 404 エラー・メッセージ・パターンを参照し、表示されるとすぐに終了します。読み取れなくなったパイプwgetに書き込もうとすると、SIGPIPE信号が受信されます。grep実際、wget最初の404エラーを受け取った直後に終了します。

関連情報