Допустим, у меня есть два tar-архива, сгенерированных немного по-другому:
$ tar tvf archive1.tar
-rw-r--r-- root/root 567 2016-09-18 14:28 member1
-rw-r--r-- root/root 1696 2016-09-18 14:28 member2
$ tar tvf archive2.tar
-rw-r--r-- root/root 567 2016-09-18 14:28 ./member1
-rw-r--r-- root/root 1696 2016-09-18 14:28 ./member2
Как извлечь member1 надежно из любого из двух архивов? Я получаю гудрон по трубе, генератор не находится под моим контролем, и хотя я могу запускать конвейер несколько раз, я бы очень хотел избежать этого без необходимости.
P.S .:
$ tar xOvf archive1.tar member1 > /dev/null
member1
$ tar xOvf archive2.tar member1 > /dev/null
tar: member1: Not found in archive
tar: Exiting with failure status due to previous errors
Похоже, переключатель командной строки --no-anchored
можете делать что хотите. Из tar (1) справочная страница (их действительно очень полезно читать или хотя бы сканировать)
- без якоря
шаблоны совпадают после любого '/' (по умолчанию для исключения)
tar -tvf test
-rw-rw-r-- iain/iain 0 2016-09-18 16:14 ./member1
-rw-rw-r-- iain/iain 0 2016-09-18 16:14 ./member2
затем
tar -xvf test member1
tar: member1: Not found in archive
tar: Exiting with failure status due to previous errors
А потом
tar -xvf test --no-anchored member1
./member1
Я был в одной лодке. tar настолько недокументирован как де-факто стандартная утилита! Большинство из нас нет Дэна рядом, так что к сожалению ...
Мой вариант использования включает в себя tar-архивы, некоторые из которых создаются программным обеспечением вне моего контроля, и наша задача - извлечь каталог верхнего уровня с именем './opt/' или 'opt /'. Это часть автоматизированного процесса создания образов виртуальных машин, и я, очевидно, хочу, чтобы он работал надежно.
То, что я придумал, далеко от общего решения, но делает то, что мне нужно, в моих ограниченных пределах. Он не будет хорошо обобщаться, если вам нужно извлечь большое количество каталогов верхнего уровня, и иметь дело со случаями, когда имена каталогов верхнего уровня неизвестны заранее, сложно.
GNU tar имеет --transform=
вариант, который принимает sed s
оператор, но, к сожалению, сопоставление с шаблоном командной строки выполняется до применения преобразования. Однако, основываясь на ответе @ user9517, за который я с радостью проголосовал, я придумал следующее элегантное решение ужасный хак, который в любом случае делает свою работу. Идея состоит в том, чтобы оба соответствовали opt/
в любом месте пути и используйте преобразование для перенаправления файлов, которые случайно совпадают opt/
где угодно, кроме верхнего уровня, во временный путь с преобразованием, который будет удален после извлечения. Полная команда выглядит так:
tar xvf $tarfile --no-anchored \
--transform='s:^\(\./\)\?[^o][^p][^t]/:.deleteme/&:' \
--show-transformed-names \
opt/
Подобное sed преобразование ломается как
^ only at the path start
\(\./\)\? match ./ if present
[^o][^p][^t] followed by any three characters that do not make "opt"
/ followed by /
В &
в заменяемой части означает исходный путь, чтобы избежать возможных конфликтов. В v
и --show-transformed-names
предназначены только для регистрации извлеченных имен.
POC. Обратите внимание на каталог sys/opt/
это ложно и нежелательно. Cwd очищали перед каждой экстракцией.
Смола в упаковке ./
префикс:
kkm@buba:~/.tmp/tarext$ tar tvf ../tar.withdot.tar
drwxr-xr-x kkm/kkm 0 2020-01-07 21:26 ./
drwxr-xr-x kkm/kkm 0 2020-01-07 21:26 ./dev/
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 ./dev/file1.dev
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 ./dev/file2.dev
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 ./dev/file3.dev
drwxr-xr-x kkm/kkm 0 2020-01-07 21:29 ./opt/
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 ./opt/file1.opt
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 ./opt/file2.opt
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 ./opt/file3.opt
drwxr-xr-x kkm/kkm 0 2020-01-07 21:26 ./sys/
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 ./sys/file1.sys
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 ./sys/file2.sys
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 ./sys/file3.sys
drwxr-xr-x kkm/kkm 0 2020-01-07 21:26 ./sys/opt/
-rw-r--r-- kkm/kkm 100 2020-01-07 20:45 ./sys/opt/file1.opt
-rw-r--r-- kkm/kkm 100 2020-01-07 20:45 ./sys/opt/file2.opt
-rw-r--r-- kkm/kkm 100 2020-01-07 20:45 ./sys/opt/file3.opt
kkm@buba:~/.tmp/tarext$ tar xvf ../tar.withdot.tar --no-anchored --transform='s:^\(\./\)\?[^o][^p][^t]/:.deleteme/&:' --show-transformed-names opt/
./opt/
./opt/file1.opt
./opt/file2.opt
./opt/file3.opt
.deleteme/sys/opt/
.deleteme/sys/opt/file1.opt
.deleteme/sys/opt/file2.opt
.deleteme/sys/opt/file3.opt
kkm@buba:~/.tmp/tarext$ rm -rf .deleteme/ ; ls -RA
.:
opt
./opt:
file1.opt file2.opt file3.opt
Tar в упаковке без префикса:
kkm@buba:~/.tmp/tarext$ tar tvf ../tar.nodot.tar
drwxr-xr-x kkm/kkm 0 2020-01-07 21:26 dev/
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 dev/file1.dev
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 dev/file2.dev
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 dev/file3.dev
drwxr-xr-x kkm/kkm 0 2020-01-07 21:29 opt/
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 opt/file1.opt
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 opt/file2.opt
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 opt/file3.opt
drwxr-xr-x kkm/kkm 0 2020-01-07 21:26 sys/
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 sys/file1.sys
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 sys/file2.sys
-rw-r--r-- kkm/kkm 100 2020-01-07 19:09 sys/file3.sys
drwxr-xr-x kkm/kkm 0 2020-01-07 21:26 sys/opt/
-rw-r--r-- kkm/kkm 100 2020-01-07 20:45 sys/opt/file1.opt
-rw-r--r-- kkm/kkm 100 2020-01-07 20:45 sys/opt/file2.opt
-rw-r--r-- kkm/kkm 100 2020-01-07 20:45 sys/opt/file3.opt
kkm@buba:~/.tmp/tarext$ tar xvf ../tar.nodot.tar --no-anchored --transform='s:^\(\./\)\?[^o][^p][^t]/:.deleteme/&:' --show-transformed-names opt/
opt/
opt/file1.opt
opt/file2.opt
opt/file3.opt
.deleteme/sys/opt/
.deleteme/sys/opt/file1.opt
.deleteme/sys/opt/file2.opt
.deleteme/sys/opt/file3.opt
kkm@buba:~/.tmp/tarext$ rm -rf .deleteme/ ; ls -RA
.:
opt
./opt:
file1.opt file2.opt file3.opt