Tar список файлов без структуры их каталогов

Tar список файлов без структуры их каталогов

Допустим, я делаю это:

tar cvf allfiles.tar $(<mylist.txt)

имой_список.txtсодержит это:

/tmp/lib1
/tmp/path2/lib2
/path3/lib3

Как заархивировать файлы так, чтобы тарбол содержал только

lib1
lib2
lib3

вообще без структуры каталогов?


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

решение1

Аргумент --xformпринимает любое количество sedвыражений-заменителей, которые очень эффективны. В вашем случае используйте шаблон, который соответствует всему до последнего, /и замените его ничем:

tar cvf allfiles.tar --xform='s|.*/||' $(<mylist.txt)

Добавьте --show-transformed-names, чтобы увидеть новые имена.

Обратите внимание, эта замена применяется ко всем именам файлов, а не только к тем, которые указаны в командной строке, так что, например, если у вас есть файл, /a/b/cа в вашем списке указано только /a, то окончательное имя файла будет просто c, а не b/c. Вы всегда можете быть более явным и предоставить точный список замен, например, в вашем случае

--xform='s|^tmp/path2/||;s|^tmp/||;s|^path3/||'

Обратите внимание, что начальный /будет удален tar (если вы не используете -P), поэтому в приведенных выше выражениях он отсутствует. Кроме того, список каталогов должен быть отсортирован так, чтобы самое длинное совпадение было выполнено первым, иначе tmp/path2/совпадения не будет, так как tmp/уже удалено. Но вы можете автоматизировать создание этого списка, например:

--xform="$(sed <mylist.txt 's|[^/]*$||; s|^/||; s:.*:s|^&||;:' | sort | tr -d '\n')"

решение2

С GNU tarвы можете использовать его -Cкогда и так часто, как захотите, с немедленным эффектом.

$ tree
.
├── 1
│   └── aaa
├── 2
│   └── bbb
└── 3
    └── ccc



# Caveat: the directory change is always relative to directory tar is using *at
# that time*, so the following doesn't work:
$ tar -cf foo.tar -C 1 aaa -C 2 bbb -C 3 ccc  
tar: 2: Cannot open: No such file or directory
tar: Error is not recoverable: exiting now

$ tar -cf foo.tar -C 1 aaa -C ../2 bbb -C ../3 ccc

$ tar tf foo.tar
aaa
bbb
ccc


# You can avoid the special case for the first directory by always specifying
# an absolute path:
$ tar -cf foo.tar -C $(pwd)/1 aaa -C $(pwd)/2 bbb -C $(pwd)/3 ccc



# Now let's create that automatically from your file:
$ cat mylist.txt
/tmp/1/aaa
/tmp/2/bbb
/tmp/3/ccc

$ while read -r line; do printf '-C %s %s ' $(dirname "$line") $(basename "$line") ; done < mylist.txt
-C /tmp/1 aaa -C /tmp/2 bbb -C /tmp/3 ccc 

# That looks about right. Let's use it in our tar command:
$ tar -cvf foo.tar $(while read -r line; do printf '-C %s %s ' $(dirname "$line") $(basename "$line") ; done < mylist.txt)
aaa
bbb
ccc

Связанный контент