tar - извлечь отбрасывающую структуру каталогов

34

unzipимеет отличный вариант -j, при котором структура каталогов архива отбрасывается, и все файлы извлекаются в один и тот же каталог.

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

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

Бенджи XVI
источник
Связано: Распаковка содержимого архива tar в родительский каталог .
G-Man говорит «Восстановить Монику»

Ответы:

79

GNU tar живет от фуритурита, поэтому, естественно, также есть несколько вариантов для этого.
http://www.gnu.org/software/tar/manual/html_node/transform.html

Если вы просто хотите удалить несколько сегментов пути, то --strip-components=nили --strip=nчасто будете делать:

 tar xvzf tgz --strip=1

Но также возможно переписать и перезаписать файлы, которые будут извлечены (флаги есть --transformили --xformпринимают ereg с /xмодификатором):

 tar xvzf tgz --xform='s#^[^/]+#.#x'
                 # or 's#^.+/##x' for discarding all paths

Для перечисления tar вам нужна дополнительная --show-transformedопция:

 tar tvzf tgz --show-transformed --strip=1 --xform='s/abc/xyz/x'

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

марио
источник
4
Почему нет s#.*/##?
10
3
- полоска только что сделала мой день. Благодарность!
SamStephens
--stripне упоминается на странице руководства os x tar, но все равно работает, спасибо!
slf
3
Гораздо лучше, чем принятый ответ.
Клаату фон Шлакер
есть ли разница между --stripи --strip-components?
Джоэл Беркли
13

Вы можете сделать это довольно легко в два этапа. При необходимости адаптируйте:

$ mkdir /tmp/dirtree
$ tar xfz /path/to/archive -C /tmp/dirtree
$ find /tmp/dirtree -type f -exec mv -i {} . \;
$ rm -rf /tmp/dirtree
MikeyB
источник
Вот как я бы это сделал (используя find -exec mv -iвместо find | xargs) .... простые шаги, которые я могу повторить в любой системе без необходимости носить с собой сценарий, чтобы сделать это для меня.
Квик-кихот
1
+1, tmpdir=$( mktemp -d )удобно при создании временных каталогов
sorki
8

pax может это сделать:

pax -v -r -s '/.*\///p' < archive.tar

или

zcat archive.tar.gz | pax -v -r -s '/.*\///p'

Вы можете сначала проверить операцию замены имени, опуская -rопцию.

HFS
источник
1

Возможное решение, которое не требует установки чего-либо.

  1. используйте, tar tvfчтобы получить все файлы из архива
  2. Извлеките эти файлы по отдельности - распакуйте tar в stdout и перенаправьте в $ filename

    tar -tvf $1 | grep -v "^d" | \
                  awk '{for(i=6;i<NF+1;i++) {printf "%s ",$i};print ""}' |\
                  while read filename
                  do
                     tar -O -xf $1 "$filename" > `basename "$filename"`
                  done
    

сохранить как extract.sh и запустить как extract.sh myfile.tar. Он также перезапишет любые повторяющиеся имена файлов, найденные в каталогах, извлеченных из архива.

DaveParillo
источник
На самом деле я только что проверил его на каком-то дереве каталогов дома, и он не работает с файлами, содержащими пробелы. Я посмотрю, не могу ли я опубликовать обновление.
DaveParillo
Исправлено, но это не так красиво, как было.
DaveParillo
-1
tar xf foo.tar.gz foo/path/to/file/bar.mp3 -O > bar.mp3

-OОпция извлекает файл на стандартный вывод, и >переадресовывает этот вывод в файл. Так что в моем примере я извлекаю foo.mp3 и перенаправляю его в bar.mp3. Имена файлов произвольны.

Клаату фон Шлакер
источник