Извлечение архива путем компоновки содержимого архива в команду tar

Я создаю самораспаковывающийся архив, и у меня есть основное дело.

Однако я хочу установить команду, которая извлекает содержимое архива tail -n+$ARCHIVE_START_LINE $0 в переменную. Я не могу заставить эту часть работать

Я пробовал много вещей здесь – один приведен ниже для объяснения. (Обратите внимание, что это упрощенный пример, и вопрос заключается в понимании труб и т. Д. Как решение проблемы.)

 #!/bin/bash export TMPDIR=`mktemp -d /tmp/selfextract.XXXXXX` ARCHIVE_START_LINE=`awk '/^__ARCHIVE_BELOW__/ {print NR + 1; exit 0; }' $0` # This works... tail -n+$ARCHIVE_START_LINE $0 | tar xzv -C $TMPDIR # .. but this is the kind of thing I want. But it doesn't work... ARCHIVE_CONTENTS=`tail -n+$ARCHIVE_START_LINE $0` echo $ARCHIVE_CONTENTS | tar xzv -C $TMPDIR # I get: gzip: stdin is a multi-part gzip file -- not supported 

Я на Ubuntu 12.04

Все ваши проблемы объясняются в: Почему мой сценарий оболочки задыхается от пробелов или других специальных символов? , но я повторю соответствующие части здесь.

Во-первых, $var в сценарии оболочки не означает «значение переменной var », это означает «принять значение переменной var , разделить ее на слова и интерпретировать каждое слово как шаблон подстановки». Чтобы избежать этих дополнительных шагов, поместите двойные кавычки вокруг переменных подстановок: "$var" означает «значение переменной var ». Всегда добавляйте двойные кавычки вокруг замещений переменных и подстановок команд, если вы не знаете и не понимаете, почему их нужно оставить.

Во-вторых, echo точно не печатает свой аргумент: он интерпретирует некоторые параметры, а в некоторых оболочках интерпретирует escape-последовательности обратного слеша. Кроме того, echo печатает конечную новую строку, которую вы можете удалить с помощью опции -n . Данные Gzipped никогда не выглядят как опция, и echo bash обращается в обратную косую черту буквально по умолчанию, но в общем случае не используйте echo на неизвестные данные, вместо этого используйте printf %s .

 printf %s "$ARCHIVE_CONTENTS" | tar xzv -C "$TMPDIR" 

Это гарантированно будет точно ARCHIVE_CONTENTS значение переменной ARCHIVE_CONTENTS .

Оставшаяся проблема, которую вы не можете решить без использования принципиально другого подхода, заключается в том, что большинство оболочек (все оболочки, которые я видел отдельно от zsh) обрезают значение переменных в первом нулевом байте (это потому, что они используют C строк с нулевым завершением под капотом). Таким образом, переменная ARCHIVE_CONTENTS фактически содержит только начало архивного файла, вплоть до первого нулевого байта. Вы не можете использовать оболочку для управления двоичными данными.

почему бы не использовать документ здесь, как в старые времена?

  #!/bin/bash export TMPDIR=`mktemp -d /tmp/selfextract.XXXXXX` ## other stuff base64 -d <<EOF | tar xvf -C $TMPDIR ## base64 encoded EOF 

вы создаете base64, закодированный таким образом

  tar cf - my_dir | base64 > /some/place 

(в том числе архив int self extract остается читателю)

Вы можете непреднамеренно расширять содержимое своего архива. Попробуйте указать свою переменную.

замещать

 echo $ARCHIVE_CONTENTS | tar xzv -C $TMPDIR 

с

 echo "$ARCHIVE_CONTENTS" | tar xzv -C $TMPDIR 

Вам также может потребоваться избегать добавления новой строки с помощью echo -n