Как я могу 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 ответов:
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
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
(доступно в GNUfind
), который говоритfind
для печати его результатов с относительными путями. Однако, если у вас нет GNUfind
, это работает, чтобы сделать пути относительными (удаляет родителей с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, чтобы ограничить включенные файлы.
tar -cvzf tarlearn.tar.gz --remove-files mytemp/*
если папка mytemp, то если вы примените выше он будет zip и удалить все файлы в папке, но оставить его в покое
tar -cvzf tarlearn.tar.gz --remove-files --exclude='*12_2008*' --no-recursion mytemp/*
вы можете дать исключить шаблоны, а также указать, чтобы не смотреть в подпапки тоже