Как создать каталог файлов и папок без включения самого каталога?
Я обычно делаю:
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`