Wget в сценарии оболочки с использованием шаблона
В настоящее время я пытаюсь настроить скрипт оболочки, использующий wget для загрузки огромного количества файлов с сервера. Я использую опцию -A 'pattern*.extension', чтобы загружать только файлы с определенным шаблоном и расширением, которые меня интересуют. (Кроме того, есть множество файлов, которые я не хочу тратить на моем ПК.) Если я запускаю wget через командную строку, все работает нормально и загружает все файлы, соответствующие шаблону. Теперь, если я попытаюсь запустить скрипт с той же самой командой wget, что и раньше, он внезапно скажет: "wget: No match". (Следует отметить, что скрипт оболочки выполняется скриптом python, который снабжен списком идентификаторов для загрузки файлов из определенных подпапок.) Но: если я напечатаю точную строку wget, скрипт оболочки выполнится и скопирует и вставит его в команду линия, это снова работает. Это просто не имеет смысла для меня.
Вот как выглядит мой wget:
wget -r -c -nH -np -nd -e robots=off -P PATH -A 'pattern*.extension' -a logfile.log --progress=bar:force --no-check-certificate https://.../ID/
А вот как в принципе выглядит мой сценарий оболочки:
#!/usr/bin/tcsh
set ID=$1 #just an ID for subfolders
set OPT2=$3 #additional options that can be passed to wget
set OPT="-r -c -nH -np -nd -e robots=off -P PATH/$ID -A 'pattern*.extension' -a $ID.log"
set OOP="--progress=bar:force --no-check-certificate"
while ($1 != '')
echo "wget $OPT $OOP $OPT2 https://.../$ID/"
wget $OPT $OOP $OPT2 https://.../$ID/
shift
end
Выходные данные следующие:
wget -r -c -nH -np -nd -e robots=off -P PATH/ID -A 'pattern*.extension' -a ID.log --progress=bar:force --no-check-certificate https://.../ID/
wget: No match.
Но теперь, если я скопирую ту самую строку, которая повторяет мой сценарий, это работает! Пожалуйста, просветите меня. Я так старался это исправить, но, очевидно, мне просто не удалось это сделать.
Также: если я заменю -A 'pattern*.extension' на -A.extenstion, он загрузит все файлы с этим расширением. По некоторым причинам это просто не работает при использовании шаблона.
Как я упоминал выше, скрипт оболочки вызывается скриптом python:
for ID in IDs:
cmd = 'csh PATH/script.csh %s' % (ID)
sub.call( cmd, shell=True )
Может быть, это также помогает, и, возможно, я должен также упомянуть, что я не очень продвинутый программист.
Заранее спасибо.
1 ответ
Я не знаком с tcsh, поэтому в tcsh может быть хорошее исправление.
Тем не менее, я знаком с bash и вижу, что может быть причиной этой проблемы. Обратите внимание на цитату здесь:
set OPT="-r -c -nH -np -nd -e robots=off -P PATH/$ID -A 'pattern*.extension' -a $ID.log"
Существует внешний слой цитат и, кроме того, внутренний слой цитат для pattern*.expansion
, Предположительно вы используете внутренний слой, потому что так выглядело бы вы, если бы вы действительно набрали команду в оболочке.
Как это работает, оболочка выполняет различные расширения в командной строке, такие как расширение переменных, расширение по шаблону и т. Д. Так в такой команде, как:
wget $OPT ...
оболочка будет расширяться $OPT
к его содержимому, выполнить разбиение поля, выделив содержимое $OPT
для разделения слов и подстановочного знака (или подстановки), в котором команда не выполняется:
> set foo="'*'"
> echo $foo
echo: No match.
> echo "$foo"
'*'
Обратите внимание, как цитаты вокруг $foo
предотвратил ошибку? Но вы не можете использовать кавычки в своем скрипте, так как кавычки также предотвратят расщепление полей, и вы полагаетесь на расщепление полей, так что различные опции в $OPT
(-r
, -c
и т. д.) передаются как отдельные аргументы wget
,
Вот демонстрация различий с цитированием и без:
> printf "|%s|\n" "$OPT"
|-r -c -nH -np -nd -e robots=off -P PATH/foo -A 'pattern*.extension' -a foo.log|
> printf "|%s|\n" $OPT
printf: No match.
> printf "|%s|\n" -r -c -nH -np -nd -e robots=off -P PATH/$ID -A 'pattern*.extension' -a $ID.log
|-r|
|-c|
|-nH|
|-np|
|-nd|
|-e|
|robots=off|
|-P|
|PATH/foo|
|-A|
|pattern*.extension|
|-a|
|foo.log|
Я думаю, это может сработать, если вы использовали:
set OPT="-r -c -nH -np -nd -e robots=off -P PATH/$ID -A pattern*.extension -a $ID.log"
Но это рискует расширением подстановочного знака, если вы не используете "$OPT"
и рабочий каталог имеет файлы, соответствующие pattern*.extension
:
> touch pattern-abc.extension
> printf "|%s|\n" $OPT
printf: No match.
> set set OPT="-r -c -nH -np -nd -e robots=off -P PATH/$ID -A pattern*.extension -a $ID.log"
> printf "|%s|\n" $OPT
|-r|
|-c|
|-nH|
|-np|
|-nd|
|-e|
|robots=off|
|-P|
|PATH/foo|
|-A|
|pattern-abc.extension| <---- tcsh expanded pattern*.extension
|-a|
|foo.log|
Опять же, я не достаточно опытен в tcsh, чтобы предложить хорошее решение, но я знаю достойное решение в bash:
Используйте массивы для построения командных строк.
В bash ваш скрипт будет выглядеть так:
#!/bin/bash
ID=$1 #just an ID for subfolders
shift
OPT2=("$@") #additional options that can be passed to wget
OPT=(-r -c -nH -np -nd -e robots=off -P PATH/"$ID" -A 'pattern*.extension' -a "$ID".log)
OOP=(--progress=bar:force --no-check-certificate)
echo wget "${OPT[@]}" "${OOP[@]}" "${OPT2[@]}" "https://.../$ID/"
wget "${OPT[@]}" "${OOP[@]}" "${OPT2[@]}" "https://.../$ID/"
Я сделал несколько изменений здесь. Вы назначили $3
в OPT2
, но затем перебрать все аргументы (по сути, это то, что while ($1 != '') ... shift
будет), но без использования этих аргументов в цикле, что не имеет смысла - второй аргумент скрипта фактически игнорируется, но третий аргумент используется как опция. Учитывая фрагмент Python, я собираюсь предположить, что только первый аргумент является идентификатором, а остальные варианты wget
,
Теперь, используя массив, вот так:
OPT=(-r -c -nH -np -nd -e robots=off -P PATH/"$ID" -A 'pattern*.extension' -a "$ID".log)
Позволяет нам расширяться до каждого отдельного слова в массиве, не рискуя разбить поле или генерировать имя файла, используя "${OPT[@]}"
в bash:
$ printf "|%s|\n" "${OPT[@]}"
|-r|
|-c|
|-nH|
|-np|
|-nd|
|-e|
|robots=off|
|-P|
|PATH/foo|
|-A|
|pattern*.extension|
|-a|
|foo.log|
Каждый аргумент прекрасно сохранился.