Вывод корневого каталога в архив tar

#shell #debian #tar

#оболочка #debian #tar

Вопрос:

Я пытаюсь автоматизировать процесс, который вы проходите при компиляции чего-то вроде nginx, используя сценарий оболочки. (Я не хочу использовать apt-get )

В настоящее время у меня есть это:

 wget http://nginx.org/download/nginx-1.0.0.tar.gz
tar xf nginx-1.0.0.tar.gz
  

Но затем мне нужно выяснить, как называется каталог, из которого он был извлечен, чтобы я мог запустить сценарий настройки.

Комментарии:

1. Смотрите команду для получения самого верхнего имени каталога в сжатых файлах вопрос по unix.stackexchange.com

Ответ №1:

Используйте это, чтобы узнать каталог (-ы) верхнего уровня архива.

 tar tzf nginx-1.0.0.tar.gz | sed -e 's@/.*@@' | uniq
  

sed вызывается здесь, чтобы получить первый компонент пути, напечатанный tar , поэтому он преобразует

 path/to/file --> path
  

Это делается путем выполнения команды. Я использую @ знак в качестве разделителя вместо более распространенного / знака, чтобы избежать экранирования / в регулярном выражении. Итак, эта команда означает: замените часть строки, которая соответствует /.* шаблону (т. Е. косой черте, за которой следует любое количество произвольных символов), на пустую строку. Или, другими словами, удалите часть строки после (и включая) первой косой черты.

(Он должен быть изменен для работы с абсолютными именами файлов; однако они довольно редки в файлах tar. Но убедитесь, что эта теоретическая возможность не создает уязвимости в вашем коде!)

Комментарии:

1. Спасибо, это было больше того, что я искал. У вас не будет секунды, чтобы объяснить, как работает это регулярное выражение sed, не так ли?

2. с tzf я получаю ошибку не в форме gzip, замена tzf на tf работает

Ответ №2:

Использование sed, как описано в другом ответе, является хорошим подходом, но его лучше использовать head -1 перед sed, а не uniq после; это имеет гораздо лучшую производительность — вы перекачиваете только первую строку через sed, и это также позволяет избежать требования uniq загружать весь вывод sed в память. Кроме того, если tar содержит несколько каталогов верхнего уровня, это вернет первый каталог верхнего уровня, тогда как uniq предоставит вам все каталоги верхнего уровня.

 tar tzf nginx-1.0.0.tar.gz | head -1 | sed -e 's//.*//'
  

Лично я считаю более удобным для чтения избегать внутреннего / в сопоставлении с шаблоном sed как / , а не вводить другой разделитель, такой как @ , но это всего лишь вопрос предпочтения

Ответ №3:

Как насчет этого для получения всех каталогов верхнего уровня (включая . ):

 tar tf nginx-1.0.0.tar.gz | xargs dirname | sort | uniq
  

Чтобы получить каталог первого верхнего уровня, я бы использовал решение, опубликованное @thomas-steinbach:

 tar tf nginx-1.0.0.tar.gz | head -1
  

Ответ №4:

Эта команда использует только tar :

 tar --exclude=*/*/* --no-wildcards-match-slash -tzf nginx-1.0.0.tar.gz
  

Забавный шаблон исключения, неэкранированный, является */*/* и означает «исключить все файлы и каталоги глубиной в два уровня»: первый * предназначен для базового каталога, второй — для файлов и каталогов первого уровня, третий — для файлов и каталогов второго уровня.

Это может сработать, только если подстановочные знаки соответствуют только именам файлов / каталогов, без косых черт. Вот почему --no-wildcards-match-slash он существует.

Ответ №5:

Имя каталога должно быть nginx-1.0.0 или любым другим именем архива без .tar.gz . Попробуйте это после wget и tar:

 cd nginx*
./configure
# etc
  

Вы также могли бы использовать переменные, если хотите.

 name='nginx-1.0.0' # or $1, or whatever works for you
wget "http://nginx.org/download/$name.tar.gz"
tar -xf "$name.tar.gz"
./$name/configure
  

Честно говоря, однако, лучшим решением было бы поместить cd в соответствующий каталог после извлечения, независимо от того, используете ли вы глобус или переменную для имени каталога.

Комментарии:

1. Я действительно не хочу вводить в него cd в качестве im-скриптинга, лучше придерживайтесь переменных. Я просто переименовал свой архив в nginx-1.0.2m.tar.gz , а затем извлек его и получил nginx-1.0.0

2. @Mint причина, по которой все обстоит именно так, заключается в условностях (архивные папки обычно имеют каталог верхнего уровня с тем же именем, что и архивная папка). Я добавлю решение с использованием переменных, но оно будет слабым. На самом деле нет причин не использовать cd.

Ответ №6:

Приведенные здесь ответы плохо работают для абсолютных путей, поскольку они сокращают их до первого каталога пути. Если вы создали архив tar с абсолютными путями, следующий фрагмент вернет его исходный корневой каталог:

 tar tf archive.tar | head -1
  

Для сжатия .tar.gz архивы добавляют опцию c. Надеюсь, это поможет некоторым другим.

Ответ №7:

Многие из приведенных выше ответов верны, но я сталкиваюсь с ситуацией, когда фактический tar остановился в результате перехода к head.

Следующая команда в командной строке:

 tar -v -zxf plotutils-3.1.tar.gz | head -1 | cut -d "/" -f 1
  

Выдаст имя верхнего каталога: plotutils-3.1
Однако результирующий каталог будет либо пустым, либо содержать один элемент.
Я использую ubuntu. Чтобы получить фактический результат tar, вы должны выполнить другую команду

 tar -zxf plotutils-3.1.tar.gz  
  

снова. Я не уверен, что делаю здесь что-то неправильно; но это следует отметить. Я обнаружил это при попытке написать сценарий оболочки для автоматического запуска сценария настройки autotool. Надеюсь, это может помочь другим.