Как я могу tar каталог файлов и папок без включения самого каталога?


Я обычно делаю:

tar -czvf my_directory.tar.gz my_directory

Что делать, если я просто хочу включить все (включая любые скрытые системные файлы) в my_directory, но не сам каталог? Я не хочу:

my_directory
   --- my_file
   --- my_file
   --- my_file

хочу:

my_file
my_file
my_file
15 293

15 ответов:

cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd - 

должен сделать работу в одной строке. Он хорошо работает и для скрытых файлов. "*"не расширяет скрытые файлы путем расширения имени пути, по крайней мере, в bash. Ниже приведен мой эксперимент:

$ mkdir my_directory
$ touch my_directory/file1
$ touch my_directory/file2
$ touch my_directory/.hiddenfile1
$ touch my_directory/.hiddenfile2
$ cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd ..
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2
$ tar ztf my_dir.tgz
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2

использовать -C переключатель дегтя:

tar -czvf my_directory.tar.gz -C my_directory .

The -C my_directory говорит tar, чтобы изменить текущий каталог на my_directory, а потом . означает "добавить весь текущий каталог" (включая скрытые файлы и подкаталоги).

убедитесь, что вы делаете -C my_directory прежде чем делать . иначе вы получите файлы в текущем каталоге.

вы также можете создать архив как обычно и извлечь его с помощью:

tar --strip-components 1 -xvf my_directory.tar.gz

посмотреть --transform/--xform, это дает вам возможность массировать имя файла, как файл добавляется в архив:

% mkdir my_directory
% touch my_directory/file1
% touch my_directory/file2
% touch my_directory/.hiddenfile1
% touch my_directory/.hiddenfile2
% tar -v -c -f my_dir.tgz --xform='s,my_directory/,,' $(find my_directory -type f)
my_directory/file2
my_directory/.hiddenfile1
my_directory/.hiddenfile2
my_directory/file1
% tar -t -f my_dir.tgz 
file2
.hiddenfile1
.hiddenfile2
file1

выражение преобразования аналогично выражению sed, и мы можем использовать разделители, кроме / (, в вышеуказанном example).
https://www.gnu.org/software/tar/manual/html_section/tar_52.html

Ответ должно работать в большинстве ситуаций. Обратите внимание, однако, как имена файлов хранятся в файле tar, как, например,./file1 а не просто file1. Я обнаружил, что это вызвало проблемы при использовании этого метода для управления tarballs, используемых в качестве файлов пакета в BuildRoot.

одним из решений является использование некоторых bash globs для перечисления всех файлов, кроме .. такой:

tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *

это трюк, который я узнал от ответ.

теперь tar вернет ошибку, если нет файлов, соответствующих ..?* или .[^.]* , но он все равно будет работать. Если ошибка является проблемой (вы проверяете успех в скрипте), это работает:

shopt -s nullglob
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
shopt -u nullglob

хотя теперь мы возимся с опциями оболочки, мы могли бы решить, что это аккуратнее, чтобы иметь * матч скрытые файлы:

shopt -s dotglob
tar -C my_dir -zcvf my_dir.tar.gz *
shopt -u dotglob

это может не работать там, где ваша оболочка глобус * в текущем каталоге, так кроме того, используйте:

shopt -s dotglob
cd my_dir
tar -zcvf ../my_dir.tar.gz *
cd ..
shopt -u dotglob
cd my_directory
tar zcvf ../my_directory.tar.gz *

TL; DR

find /my/dir/ -printf "%P\n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

С некоторыми условиями (архив только файлы, dirs и символические ссылки):

find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

объяснение

ниже, к сожалению, включает в себя родительский каталог ./ в архиве:

tar -czf mydir.tgz -C /my/dir .

вы можете переместить все файлы из этого каталога с помощью --transform опция конфигурации, но это не избавляет от . сам каталог. Становится все труднее приручить команда.

вы могли бы использовать $(find ...) добавить список файлов в команду (как в Магнус ответа), но это потенциально вызывает ошибку "список файлов слишком длинный". Лучший способ-объединить его с tar , например:

find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

это список всех файлов (-type f), ссылки (-type l) и подкаталоги (-type d) в вашем каталоге сделайте все имена файлов относительными с помощью -printf "%P\n", а затем передайте это команде tar (it принимает имена файлов из STDIN с помощью -T -). Элемент -C опция необходима, чтобы tar знал, где находятся файлы с относительными именами. Элемент --no-recursion флаг так, что деготь не рекурсивно по папкам сказано в архиве (вызывая повторяющиеся файлы).

Если вам нужно сделать что-то особенное с именами файлов (фильтрация, следующие символические ссылки и т. д.),find команда довольно мощная, и вы можете проверить ее, просто удалив tar часть выше команда:

$ find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d
> textfile.txt
> documentation.pdf
> subfolder2
> subfolder
> subfolder/.gitignore

например, если вы хотите отфильтровать PDF файлы, добавьте ! -name '*.pdf'

$ find /my/dir/ -printf "%P\n" -type f ! -name '*.pdf' -o -type l -o -type d
> textfile.txt
> subfolder2
> subfolder
> subfolder/.gitignore

non-GNU find

команда использует printf (доступно в GNU find), который говорит find для печати его результатов с относительными путями. Однако, если у вас нет GNU find, это работает, чтобы сделать пути относительными (удаляет родителей с sed):

find /my/dir/ -type f -o -type l -o -type d | sed s,^/my/dir/,, | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

Если это система Unix / Linux, и вы заботитесь о скрытых файлах (которые будут пропущены*), вам нужно сделать:

cd my_directory
tar zcvf ../my_directory.tar.gz * .??*

Я не знаю, как выглядят скрытые файлы под Windows.

Я бы предложил следующую функцию Bash (первый аргумент-это путь к dir, второй аргумент-это базовое имя результирующего архива):

function tar_dir_contents ()
{
    local DIRPATH=""
    local TARARCH=".tar.gz"
    local ORGIFS="$IFS"
    IFS=$'\n'
    tar -C "$DIRPATH" -czf "$TARARCH" $( ls -a "$DIRPATH" | grep -v '\(^\.$\)\|\(^\.\.$\)' )
    IFS="$ORGIFS"
}

вы можете запустить его таким образом:

$ tar_dir_contents /path/to/some/dir my_archive

и он будет генерировать архиве my_archive.tar.gz в текущем каталоге. Он работает со скрытыми (.* ) элементы и с элементами с пробелами в их имени файла.

cd my_directory && tar -czvf ../my_directory.tar.gz $(ls -A) && cd ..

этот работал для меня, и он включает все скрытые файлы, не помещая все файлы в корневой каталог с именем "."как в Томоэ это :

использовать pax.

Pax является устаревшим пакетом, но делает работу отлично и простым способом.

pax -w > mydir.tar mydir
find $TARGET_DIR -maxdepth 1 -type f -print0 \
| xargs --null --max-args 1 basename --zero \
| tar --create --file=result.tar --directory=$TARGET_DIR --null --files-from=-

предполагается, что вы не хотите включать подкаталоги или файлы из всех подкаталогов. Безопасно обрабатывает имена файлов с пробелами или другими необычными персонажами. Вы можете дополнительно добавить -name '*.sql' или аналогичный фильтр для команды find, чтобы ограничить включенные файлы.

самый простой способ, который я нашел:

cd my_dir & & tar-czvf ../my_dir.смола.gz*

 tar -cvzf  tarlearn.tar.gz --remove-files mytemp/*

если папка mytemp, то если вы примените выше он будет zip и удалить все файлы в папке, но оставить его в покое

 tar -cvzf  tarlearn.tar.gz --remove-files --exclude='*12_2008*' --no-recursion mytemp/*

вы можете дать исключить шаблоны, а также указать, чтобы не смотреть в подпапки тоже

tar -C my_dir -zcvf my_dir.tar.gz `ls my_dir`