web-dev-qa-db-ja.com

404を取得した後、「wget」をどのように停止しますか?

wgetでブレース展開を使用すると、連続番号の付いた画像を簡単にフェッチできます。

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

90.jpgから99.jpgまでの番号が付いた最初の10個のファイルを正常にフェッチしますが、100.jpg以降は404:File not foundエラーを返します(画像は100枚しかありません)サーバーに保存されます)。これらの存在しないファイルは、{00..200}などのより大きな範囲を使用すると、「問題」が多くなり、100個の存在しないファイルを使用すると、スクリプトの実行時間が増加し、わずかな負担になる場合もあります(またはサーバー上で少なくとも煩わしい)。

最初の404エラーを受け取った後にwgetを停止する方法はありますか? (または、別の理由で範囲内にファイルが欠落している場合は、続けて2つ続けます)中括弧の展開を使用する必要はありません。ループも結構です。

12
IQAndreas

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

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

これにより、展開内の各URLに対してwgetが実行され、失敗するまで実行されます。その後、ループの外で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にはそのための機能が組み込まれているとは思いません。

9
Michael Homer

GNU Parallelでは、これは機能するはずです:

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

バージョン20140722以降では、「2つの行を連続して」ほぼ失敗する可能性があります。--halt 2%を指定すると、ジョブの2%が失敗します。

parallel --halt 2% wget ::: 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg'
2
Ole Tange

wgetの終了コード/ステータスに焦点を合わせたIMOは、一部のユースケースでは単純すぎる場合があるため、ここでは、HTTPステータスコードを考慮して、詳細な意思決定を行うものを示します。

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

#!/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
1
shalomb