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

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

tar -czvf my_directory.tar.gz my_directory

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

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

Я хочу:

my_file
my_file
my_file

Ответ 1

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

Ответ 2

Используйте переключатель -C для tar:

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

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

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

Ответ 3

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

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

Ответ 4

Посмотрите --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, и мы можем использовать разделители, отличные от / (, в приведенном выше примере).
https://www.gnu.org/software/tar/manual/html_section/tar_52.html

Ответ 5

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

Одним из решений является использование некоторых Bash globs для перечисления всех файлов, кроме .. следующим образом:

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

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

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

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

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

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

Ответ 6

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

Ответ 7

TL; DR

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

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

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 ...), чтобы добавить список файлов в команду (например, в magnus 'answer), но это потенциально вызывает слишком длинный список файлов, ошибка. Лучший способ - объединить его с параметром tar -T, например:

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 (он принимает имена файлов из STDIN с помощью -T -). Опция -C необходима, так что tar знает, где находятся файлы с относительными именами. Флаг --no-recursion таков, что tar не переписывает в папки, которые, как говорят, архивируются (вызывая дубликаты файлов).

Если вам нужно сделать что-то особенное с именами файлов (фильтрация, следующие символические ссылки и т.д.), команда 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

Поиск не-GNU

В команде используется 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 -

Ответ 8

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

function tar_dir_contents ()
{
    local DIRPATH="$1"
    local TARARCH="$2.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 в текущем каталоге. Он работает со скрытыми (. *) Элементами и элементами с пробелами в имени файла.

Ответ 9

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

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

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

Ответ 10

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

Pax - это устаревший пакет, но делает работу идеально и простым способом.

pax -w > mydir.tar mydir

Ответ 11

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, чтобы ограничить вложенные файлы.

Ответ 12

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

Этот работал у меня, и он включал все скрытые файлы, не помещая все файлы в корневой каталог с именем ".". как в tomoe answer:

Ответ 13

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

cd my_dir && tar -czvf../my_dir.tar.gz *

Ответ 14

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

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

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

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

Ответ 15

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