Как выбрать имя каталога во время распаковки

125

Скажем, у меня есть файл с именем ugly_name.tar, который при извлечении становится ugly_nameкаталогом. Какую команду я могу использовать, чтобы полученное имя каталога было pretty_nameвместо этого?

tshepang
источник

Ответы:

172

Это должно работать:

mkdir pretty_name && tar xf ugly_name.tar -C pretty_name --strip-components 1

-Cизменения в указанном каталоге перед распаковкой (или упаковкой). --strip-componentsудаляет указанное количество каталогов из имен файлов, хранящихся в архиве.

Обратите внимание, что это не совсем переносимо. GNU tar и, по крайней мере, некоторые из BSD-таров имеют --strip-componentsопцию, но, похоже, не существуют на других Unix-подобных платформах.

Хотя глупый способ сделать это работал бы почти везде.

tar xf ugly_name.tar && mv ugly_name pretty_name
Мат
источник
Я думаю, что я буду придерживаться тупой версии :)
phunehehe
28
@phunehehe: одним из преимуществ умной версии является то, что вам не нужно заранее знать, как называется каталог без изменений
tshepang
2
Могу ли я добавить, что это работает больше, чем "Pretty_name". Вы также можете распаковать в конкретный каталог таким образом. Пример:tar -xvf /tmp/backupfiles.tar -C /var/www/
Генерал Реднек
2
Я обычно использую тупой способ, и я использую подстановочные знаки в случае, если я не знаю, какое будет уродливое имя, или я не хочу записывать его. mv ugly-* pretty_name
Дэвид Грейсон
1
Тупой путь не работает, если ugly_nameкаталог уже есть . Кстати, красота в глазах смотрящего.
kmiklas
30

С GNU tar ≥1.16 используйте --transformдля применения преобразования sed regexp к каждому имени файла (преобразование применяется к полному пути в архиве):

tar xf foo.tar --transform 's!^ugly_name\($\|/\)!pretty_name\1!'

Если ugly_nameкомпонент верхнего уровня всех имен файлов в архиве, вам не нужно беспокоиться о точном сопоставлении:

tar xf foo.tar --transform 's/ugly_name/pretty_name/'

Если вы не знаете имя каталога верхнего уровня, вы все равно можете использовать этот метод, хотя --strip-componentsвместо этого вы можете предпочесть .

tar xf foo.tar --transform 's!^[^/]\+\($\|/\)!pretty_name\1!'

С paxпомощью утилиты архивирования POSIX используйте -sопцию, которая принимает в качестве аргумента выражение замены, похожее на sed.

pax -rf foo.tar -s '!^ugly_name\($\|/\)!pretty_name\1!'
pax -rf foo.tar -s '/ugly_name/pretty_name/'
pax -rf foo.tar -s '!^[^/]\+\($\|/\)!pretty_name\1!'
жилль
источник
9

Использовать это :

tar -xvf ugly_name.tar
mv ugly_name pretty_name
Рупеш Манде
источник
9
Вы можете предпочесть использовать &&оператор списка между этими двумя командами, поэтому вторая будет выполнена, только если первая выполнилась успешно.
manatwork
1
Это может иметь нежелательные последствия, если каталог ugly_nameуже существует.
Дрю
7

Самый простой способ

tar xvf dml/ugly_name.tar --one-top-level=pretty_name --strip-components 1
marquicus
источник
(1) Это явно не самый простой способ, так как smac89 опубликовал ответ отличая --one-top-level=pretty_nameбез --strip-components 1. (2) И наоборот, принятый ответ (опубликованный Mat)--strip-components 1 без функций --one-top-level=pretty_name. (3) Можете ли вы объяснить, почему ваш ответ, сочетающий эти варианты, лучше, чем любой из более старых? Пожалуйста, не отвечайте в комментариях; отредактируйте  свой ответ, чтобы сделать его более понятным и полным.
G-Man
может быть, реальный пример может помочь вам уточнить: `wget dev.mysql.com/get/Downloads/MySQL-5.7/… tar xvf mysql-5.7.23-linux-glibc2.12-x86_64.tar.gz --one-top -level = mysql57 --strip-components 1 `
marquicus
Этот ответ более изящен, чем тот, у которого больше всего голосов .
KaiserKatze
@ G-Man --strip-component 1требуется либо методом, mkdirлибо --strip-components 1, иначе вы просто получите pretty_name/ugly_name/.
Дэвид
Это действительно самый простой способ
smac89
2

От askUbuntu этот ответ работал для меня:

tar zxvf ugly_name.tgz --one-top-level=pretty_name

`--One-верхнего уровня [= DIR]

Указывает tar создать новый каталог под каталогом извлечения (или переданным в `-C ') и использовать его для защиты от тарбомб. При отсутствии аргумента dir имя нового каталога будет равно базовому имени архива (имя файла минус суффикс архива, если он распознан). Любые имена членов, которые не начинаются с этого имени каталога (после преобразований из `--transform 'и` --strip-components'), будут иметь префикс. Распознаются суффиксы имен файлов `.tar ', а любые суффиксы сжатия распознаются с помощью See -auto-compress .


Обновить

Как отмечено в комментариях , этот метод не работает для архивов, которые правильно сформированы, однако, как показывает другой ответ , вы должны добавить, --strip-components 1чтобы это действительно работало. Я проверил с этой новой опцией, и она работает как для архивов с именем верхнего уровня, так и без.

smac89
источник
Проблема заключается в том, что он не переименовывает каталог верхнего уровня, а создает новый уровень с именем pretty_name, в котором находится исходный каталог верхнего уровня. Например, если tar xzf ugly_name.tgzбы создать каталог с именем ugly_name/, то команда, которую вы предоставили, создаст pretty_name/ugly_name/.
Дэвид
1
@davidA Хорошая мысль. Я обновил свой ответ, чтобы включить исправление для этого
smac89