检查bash中是否存在远程文件

Adr*_*ian 10 bash wget gnu-parallel

我正在使用此脚本下载文件:

parallel --progress -j16 -a ./temp/img-url.txt 'wget -nc -q -P ./images/ {}; wget -nc -q -P ./images/ {.}_{001..005}.jpg'
Run Code Online (Sandbox Code Playgroud)

是不是可以不下载文件,只是在远程端检查它们,如果存在则创建一个虚拟文件而不是下载?

就像是:

if wget --spider $url 2>/dev/null; then
  #touch img.file
fi
Run Code Online (Sandbox Code Playgroud)

应该工作,但我不知道如何将此代码与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 {}
Run Code Online (Sandbox Code Playgroud)

它可以工作,但它对某些文件失败了.我无法找到为什么它适用于某些文件的一致性,为什么它对其他文件失败.也许它有最后一个文件名的东西.第二个wget尝试访问当前url,但之后的touch命令根本不会创建desidered文件.第一个wget总是(正确地)下载没有_001.jpg,_002.jpg的主图像.

示例urls.txt:

http://host.com/092401.jpg(工作正常,_001.jpg .._ 005.jpg下载) http://host.com/HT11019.jpg(不起作用,只下载主图像)

Any*_*ine 6

您可以使用curl以下方法来检查您正在解析的 URL 是否存在,而无需下载任何文件:

if curl --head --fail --silent "$url" >/dev/null; then
    touch .images/"${url##*/}"
fi
Run Code Online (Sandbox Code Playgroud)

解释:

  • --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
Run Code Online (Sandbox Code Playgroud)


Ole*_*nge 5

很难理解你真正想要完成的是什么。让我试着重新表述你的问题。

我已经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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

example.org这些 URL 上存在:

http://example.org/dira/foo_001.jpg
Run Code Online (Sandbox Code Playgroud)

鉴于urls.txt我想生成与 _001.jpg .. _005.jpg 的组合以及原始 URL。例如:

http://example.com/dira/foo.jpg
Run Code Online (Sandbox Code Playgroud)

变成:

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
Run Code Online (Sandbox Code Playgroud)

然后我想在不下载文件的情况下测试这些 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
Run Code Online (Sandbox Code Playgroud)

(版本 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
Run Code Online (Sandbox Code Playgroud)

(版本 3):我想要在 dir 中创建的images名为 name from的空文件urls.txt。这是可以做到的,因为只有 _001.jpg .. _005.jpg 之一存在。

images/foo.jpg
images/bar.jpg
images/baz.jpg
Run Code Online (Sandbox Code Playgroud)
#!/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
Run Code Online (Sandbox Code Playgroud)

GNU Parallel 每个作业需要几毫秒。当你的工作这么短时,开销会影响时间。如果您的 CPU 内核均未以 100% 运行,您可以并行运行更多作业:

parallel -j0 do_url {1.}{2} {1//} {1/.}{2} {1/} :::: urls.txt ::: .jpg _{001..005}.jpg
Run Code Online (Sandbox Code Playgroud)

您还可以“展开”循环。这将为每个 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
Run Code Online (Sandbox Code Playgroud)

最后,您可以运行 250 多个作业:https : //www.gnu.org/software/parallel/man.html#EXAMPLE : -Running- more-than-250-jobs- workaround