Проверьте, существует ли удаленный файл в bash
я загружаю файлы с помощью этого скрипта:
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.
Edit:
на основе ответа Ole я написал этот фрагмент кода:
#!/bin/bash
do_url() {
  url=""
  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 {}
он работает, но он терпит неудачу для несколько файлов. Я не могу найти последовательность, почему она работает для некоторых файлов, почему она терпит неудачу для других. Может, там есть что-то с последним именем. Второй wget пытается получить доступ к url-адресу currect, но команда touch после этого просто не создает желаемый файл. Сначала wget всегда (правильно) загружает основное изображение без _001.формат JPG, _002.формат jpg.
пример url-адреса.txt:
http://host.com/092401.jpg (работает правильно, _001.формат jpg.._005.архив jpg загруженный) http://host.com/HT11019.jpg (не работает, загружается только основное изображение)
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.jpgOn эти 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.jpgOn эти URL-адреса:
http://example.org/dira/foo_001.jpgдано
urls.txtЯ хочу создать комбинации с _001.формат jpg.. _005.jpg в дополнение к исходному URL. Например: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. Это необходимо, потому что некоторые из изображений имеют одно и то же имя, но в разных dirs.Итак, файлы должно быть:
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): я хочу, чтобы пустой файл был создан в dir
imagesназвал имя изurls.txt. Это можно сделать, потому что только один из _001.формат jpg.. _005.jpg существует.images/foo.jpg images/bar.jpg images/baz.jpg
#!/bin/bash
do_url() {
  url=""
  # 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/"" && 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/""
  # 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/""
}
export -f do_url
parallel do_url {1.}{2} {1//} {1/.}{2} {1/} :::: urls.txt ::: .jpg _{001..005}.jpg
GNU Parallel принимает несколько МС на работу. Когда ваши задания так коротки, накладные расходы повлияют на сроки. Если ни одно из ваших ядер процессора не работает на 100%, вы можете запускать больше заданий параллельно:
parallel -j0 do_url {1.}{2} {1//} {1/.}{2} {1/} :::: urls.txt ::: .jpg _{001..005}.jpg
вы также можете "развернуть" цикл. Это позволит сэкономить 5 накладных расходов на URL:
do_url() {
  url=""
  # 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будет избегать состояния или ошибок от испускания самой проверки. 
чтобы решить проблему "зацикливания", вы можете do:
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
что это делает, так это то, что он вызывает Wget с . С HEAD запрос, сервер просто сообщит, существует ли файл или нет, без возврата каких-либо данных.
конечно, с большими данными установить это довольно неэффективно. Вы создаете новое соединение с сервером для каждого файла, который вы пытаетесь. Вместо этого, как было предложено в другом ответе, вы можете использовать GNU Wget2. С помощью wget2 вы можете проверить все это параллельно и использовать новый найти список всех файлов и конкретный код возврата, что сервер. Например:
$ 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
вы можете отправить команду через ssh, чтобы узнать, существует ли удаленный файл, и cat, если это так:
ssh your_host 'test -e "somefile" && cat "somefile"' > somefile
также можно попробовать scp, который поддерживает выражения glob и рекурсию.