私はこのスクリプトでファイルをダウンロードしています:
parallel --progress -j16 -a ./temp/img-url.txt 'wget -nc -q -P ./images/ {}; wget -nc -q -P ./images/ {.}_{001..005}.jpg'
ファイルをダウンロードせず、リモート側で確認し、存在する場合はダウンロードせずにダミーファイルを作成することは可能でしょうか?
何かのようなもの:
if wget --spider $url 2>/dev/null; then
#touch img.file
fi
動作するはずですが、このコードをGNU Parallelと組み合わせる方法がわかりません。
編集:
Oleの回答に基づいて、私は次のコードを作成しました。
#!/bin/bash
do_url() {
url="$1"
wget -q -nc --method HEAD "$url" && touch ./images/${url##*/}
#get filename from $url
url2=${url##*/}
wget -q -nc --method HEAD ${url%.jpg}_{001..005}.jpg && touch ./images/${url2%.jpg}_{001..005}.jpg
}
export -f do_url
parallel --progress -a urls.txt do_url {}
動作しますが、一部のファイルでは失敗します。一部のファイルで機能する理由、他のファイルで失敗する理由の一貫性が見つかりません。たぶんそれは最後のファイル名で何かを持っています。 2番目のwgetは現在のURLにアクセスしようとしますが、その後のtouchコマンドは単に目的のファイルを作成しません。最初のwgetは、常に(正しく)_001.jpg、_002.jpgなしでメインイメージをダウンロードします。
Urls.txtの例:
http://Host.com/092401.jpg (正しく動作し、_001.jpg .._ 005.jpgがダウンロードされます) http://Host.com/HT11019.jpg =(機能しません。メイン画像のみがダウンロードされます)
あなた本当にが達成したいことを理解するのはかなり難しいです。あなたの質問を言い換えてみましょう。
私は
urls.txt
を含んでいます:http://example.com/dira/foo.jpg http://example.com/dira/bar.jpg http://example.com/dirb/foo.jpg http://example.com/dirb/baz.jpg http://example.org/dira/foo.jpg
example.com
には、次のURLが存在します。http://example.com/dira/foo.jpg http://example.com/dira/foo_001.jpg http://example.com/dira/foo_003.jpg http://example.com/dira/foo_005.jpg http://example.com/dira/bar_000.jpg http://example.com/dira/bar_002.jpg http://example.com/dira/bar_004.jpg http://example.com/dira/fubar.jpg http://example.com/dirb/foo.jpg http://example.com/dirb/baz.jpg http://example.com/dirb/baz_001.jpg http://example.com/dirb/baz_005.jpg
example.org
には、次のURLが存在します。http://example.org/dira/foo_001.jpg
urls.txt
が与えられた場合、元のURLに加えて、_001.jpg .._ 005.jpgとの組み合わせを生成したいと思います。例えば。:http://example.com/dira/foo.jpg
になります:
http://example.com/dira/foo.jpg http://example.com/dira/foo_001.jpg http://example.com/dira/foo_002.jpg http://example.com/dira/foo_003.jpg http://example.com/dira/foo_004.jpg http://example.com/dira/foo_005.jpg
次に、ファイルをダウンロードせずにこれらのURLが存在するかどうかをテストしたいと思います。 URLがたくさんあるので、これを並行して実行したいと思います。
URLが存在する場合は、空のファイルを作成します。
(バージョン1):dir
images
の同様のディレクトリ構造に空のファイルを作成したい。一部の画像の名前は同じですが、ディレクトリが異なるため、これが必要になります。したがって、作成されるファイルは次のようになります。
images/http:/example.com/dira/foo.jpg images/http:/example.com/dira/foo_001.jpg images/http:/example.com/dira/foo_003.jpg images/http:/example.com/dira/foo_005.jpg images/http:/example.com/dira/bar_000.jpg images/http:/example.com/dira/bar_002.jpg images/http:/example.com/dira/bar_004.jpg images/http:/example.com/dirb/foo.jpg images/http:/example.com/dirb/baz.jpg images/http:/example.com/dirb/baz_001.jpg images/http:/example.com/dirb/baz_005.jpg images/http:/example.org/dira/foo_001.jpg
(バージョン2):dir
images
に空のファイルを作成したい。これは、すべての画像に一意の名前があるために実行できます。したがって、作成されるファイルは次のようになります。
images/foo.jpg images/foo_001.jpg images/foo_003.jpg images/foo_005.jpg images/bar_000.jpg images/bar_002.jpg images/bar_004.jpg images/baz.jpg images/baz_001.jpg images/baz_005.jpg
(バージョン3):ディレクトリ
images
に作成された、urls.txt
からの名前と呼ばれる空のファイルが必要です。これは、_001.jpg .._ 005.jpgが1つしか存在しないために実行できます。images/foo.jpg images/bar.jpg images/baz.jpg
#!/bin/bash
do_url() {
url="$1"
# Version 1:
# If you want to keep the folder structure from the server (similar to wget -m):
wget -q --method HEAD "$url" && mkdir -p images/"$2" && touch images/"$url"
# Version 2:
# If all the images have unique names and you want all images in a single dir
wget -q --method HEAD "$url" && touch images/"$3"
# Version 3:
# If all the images have unique names when _###.jpg is removed and you want all images in a single dir
wget -q --method HEAD "$url" && touch images/"$4"
}
export -f do_url
parallel do_url {1.}{2} {1//} {1/.}{2} {1/} :::: urls.txt ::: .jpg _{001..005}.jpg
GNU Parallelは、ジョブごとに数ミリ秒かかります。ジョブがこれほど短い場合、オーバーヘッドがタイミングに影響します。 CPUコアが100%で実行されていない場合は、さらに多くのジョブを並行して実行できます。
parallel -j0 do_url {1.}{2} {1//} {1/.}{2} {1/} :::: urls.txt ::: .jpg _{001..005}.jpg
ループを「展開」することもできます。これにより、URLごとに5つのオーバーヘッドが節約されます。
do_url() {
url="$1"
# Version 2:
# If all the images have unique names and you want all images in a single dir
wget -q --method HEAD "$url".jpg && touch images/"$url".jpg
wget -q --method HEAD "$url"_001.jpg && touch images/"$url"_001.jpg
wget -q --method HEAD "$url"_002.jpg && touch images/"$url"_002.jpg
wget -q --method HEAD "$url"_003.jpg && touch images/"$url"_003.jpg
wget -q --method HEAD "$url"_004.jpg && touch images/"$url"_004.jpg
wget -q --method HEAD "$url"_005.jpg && touch images/"$url"_005.jpg
}
export -f do_url
parallel -j0 do_url {.} :::: urls.txt
最後に、250を超えるジョブを実行できます。 https://www.gnu.org/software/parallel/man.html#EXAMPLE:-Running-more-than-250-jobs-workaround
代わりにcurl
を使用して、ファイル自体をダウンロードせずに、解析しているURLがそこにあるかどうかを確認できます。
if curl --head --fail --silent "$url" >/dev/null; then
touch .images/"${url##*/}"
fi
説明:
--fail
は、失敗した要求で終了ステータスをゼロ以外にします。--head
ファイルの内容のダウンロードを回避します--silent
は、ステータスまたはエラーがチェック自体によって発行されるのを回避します。「ループ」の問題を解決するには、次のようにします。
urls=( "${url%.jpg}"_{001..005}.jpg )
for url in "${urls[@]}"; do
if curl --head --silent --fail "$url" > /dev/null; then
touch .images/${url##*/}
fi
done
私が見る限り、あなたの質問は、実際にはwget
を使用してファイルの存在をテストする方法ではなく、シェルスクリプトで正しいループを実行する方法に関するものです。
そのための簡単な解決策は次のとおりです。
urls=( "${url%.jpg}"_{001..005}.jpg )
for url in "${urls[@]}"; do
if wget -q --method=HEAD "$url"; then
touch .images/${url##*/}
fi
done
これは、--method=HEAD
オプションを指定してWgetを呼び出すことです。 HEAD
リクエストを使用すると、サーバーはデータを返さずに、ファイルが存在するかどうかを単に報告します。
もちろん、大きなデータセットでは、これはかなり非効率的です。試行しているファイルごとに、サーバーへの新しい接続を作成しています。代わりに、他の回答で提案されているように、GNU Wget2を使用できます。wget2を使用すると、これらすべてを並行してテストし、新しい--stats-server
オプションを使用してリストを見つけることができます。サーバーが提供したすべてのファイルと特定の戻りコードの例:
$ wget2 --spider --progress=none -q --stats-site example.com/{,1,2,3}
Site Statistics:
http://example.com:
Status No. of docs
404 3
http://example.com/3 0 bytes (identity) : 0 bytes (decompressed), 238ms (transfer) : 238ms (response)
http://example.com/1 0 bytes (gzip) : 0 bytes (decompressed), 241ms (transfer) : 241ms (response)
http://example.com/2 0 bytes (identity) : 0 bytes (decompressed), 238ms (transfer) : 238ms (response)
200 1
http://example.com/ 0 bytes (identity) : 0 bytes (decompressed), 231ms (transfer) : 231ms (response)
このデータをCSVまたはJSONとして印刷して、解析を容易にすることもできます。
名前をループするだけですか?
for uname in ${url%.jpg}_{001..005}.jpg
do
if wget --spider $uname 2>/dev/null; then
touch ./images/${uname##*/}
fi
done