web-dev-qa-db-ja.com

curlの代わりにaria2を使用すると、文字列の連結が壊れます

サイトを_archive.org_にミラーリングしようとしていますが、curlの使用が非常に遅いため、代わりに_aria2_を試してみました。

まず、このコマンドを使用してサイトのリンクマップを作成します

_wget -c -m --restrict-file-names=nocontrol https://www.example.com/
_

次に、curlを使用してこのコマンドを実行します

_find . -type f -exec curl -v "https://web.archive.org/save/https://{}" ';'
_

(実際、私はこのコマンドを使用して、自分が行っていたことの十分なログを取得しました

find . -type f -exec curl -v "https://web.archive.org/save/https://{}" ';' 2> >(grep 'Rebuilt URL' >>/tmp/error ) >/tmp/stdout-参照用にここに含めました)

これは正常に機能していました。findコマンドは次のような出力を生成しました。

_./www.example.com/index
_

そしてcurlは先頭の_./_を魔法のように無視しました

ええと、Aria2はそれほど賢くありませんでした。このコマンド

_find . -type f -exec aria2c -x 16 -s 1 "https://web.archive.org/save/https://{}" ';'
_

このエラーにつながる:

_07/24 23:40:45 [ERROR] CUID#7 - Download aborted. URI=https://web.archive.org/save/https://./www.example.com/index
_

(URLの途中にある余分な_./_に注意してください)。

それから私は見つけました この質問 それは私がfindからの出力を変更するのを助けました

_find . -type f -printf '%P\n'
_

戻り値

_www.example.com/index
_

(先頭の_./_はありません)

ただし、これをaria2にフィードすると、連結されたURLstillの途中に_./_が含まれます!?!?

_find . -type f -printf '%P\n' -exec aria2c -x 16 -s 1 "https://web.archive.org/save/https://{}" ';'
_

このエラーメッセージを表示します

_www.example.com/index

07/24 23:52:34 [NOTICE] Downloading 1 item(s)
[#d44753 0B/0B CN:1 DL:0B]                                                                                     
07/24 23:52:35 [ERROR] CUID#7 - Download aborted. URI=https://web.archive.org/save/https://./www.example.com/index
Exception: [AbstractCommand.cc:351] errorCode=29 URI=https://web.archive.org/save/https://./www.example.com/index
  -> [HttpSkipResponseCommand.cc:232] errorCode=29 The response status is not successful. status=502

07/24 23:52:35 [NOTICE] Download GID#d44753fe24ebf448 not complete: 

Download Results:
gid   |stat|avg speed  |path/URI
======+====+===========+=======================================================
d44753|ERR |       0B/s|https://web.archive.org/save/https://./www.example.com/index
_

_./_を削除して、aria2に適切で正しいURLが提供されるようにするにはどうすればよいですか?

ボーナスの質問:

  1. URLを処理した後、ページを(再)移動できれば素晴らしいと思います。つまり、インデックスを_./www.example.com/index_から_./processed/www.example.com/index_に移動します。それ、どうやったら出来るの? execコマンドのfindに何かありますか?それとも、本格的なスクリプトが必要ですか?

  2. この目的のためのaria2の最適な設定は何ですか?

1
hensti

-exec-printfから独立しているため、最後のものは機能しません。

ただし、-execの代わりにxargsを使用できます。

find . -type f -printf '%P\n' \
    | xargs -I{} aria2c -x 16 -s 1 "https://web.archive.org/save/https://{}"

複数のaria2cインスタンスをxargs -P <num>と並行して実行することもできます。


さらに良いオプションは、パイプとfindを使用する代わりに、aria2の入力としてxargsからファイル記述子を作成することです。

aria2c -x 16 -s 1 -i <(find . -type f -printf 'https://web.archive.org/save/https://%P\n')
1
pLumo

-printfを追加すると、出力が生成されるだけで、{}が置き換えられるものは変更されません。

curlは、aria2よりも少し賢い(または、より多くの魔法を適用する)ようで、./を削除します。見つかったパス名の最初の./は、findが検索を開始する最上位ディレクトリに相対的なパス名を生成するという事実に由来します。

最初のaria2を含まないURLで./またはcurlを呼び出すには、次を使用します。

find . -type f -exec sh -c '
    for pathname do
        pathname=${pathname#./}
        aria2c -x 16 -s 1 "https://web.archive.org/save/https://$pathname"
    done' sh {} +

これにより、見つかったパス名の束を持つ子シェルが呼び出されます。子シェルはこれらをループし、呼び出す前に標準のパラメーター展開を使用して最初の./を削除します。この場合は、aria2cです。

一般に:

topdir=/some/directory/path  # no '/' at the end

find "$topdir" -type f -exec sh -c '
    topdir="$1"; shift
    for pathname do
        pathname=${pathname#$topdir/}
        aria2c -x 16 -s 1 "https://web.archive.org/save/https://$pathname"
    done' sh "$topdir" {} +

関連:

0
Kusalananda