
Я использую эту команду для архивации каталога, названного g
из кода Java:
tar czf /a/b/c.tar.gz /e/f/g
c.tar.gz
Когда создается файл tar , я нахожу полный путь e/f/g
, а затем все файлы g
папки внутри него. Но я хочу видеть только файлы в папке g
в сжатом архиве, когда я его открываю. Как удалить папки /e/f/
в файле .tar.gz?
решение1
tar -czf /a/b/c.tar.gz -C /e/f/g .
Эта -C
опция позволяет tar
изменить рабочий каталог, поэтому вам нужно только добавить .
.
решение2
Этот вопрос возник некоторое время назад, но я до сих пор не смог найти для себя ответ, как легко добавлять файлы и папки с определенными критериями поиска с относительными путями.
Следующее охватывает более широкую тему, чем та, о которой спрашивали. Итак, я пишу решение, которое я нашел после своего исследования.
Предположим, что ваша $input_dir
переменная указывает на интересующий вас каталог, и вы хотите заархивировать и сжать (используя gzip) все ваши *.txt
файлы в ~/my_txt.tar.gz
. Чтобы создать сжатый gzip tarball без пути, сохраненного в tar (относительный путь), используйте следующее:
find "$input_dir" -maxdepth 1 -type f -name "*.txt" -printf "%P\0" | tar --null --create --remove-files --gzip --file="$HOME/my_txt.tar.gz" --directory="$input_dir" --files-from=-
Давайте разберемся:
"$input_dir"
: Начальный каталог. Измените его на любой другой, который вам нравится.maxdepth 1
: ищет только в корне этого каталога. Вы можете удалить или изменить его, если хотите искать на всех или на разных уровнях.-type f
: искать только файлы-name "*.txt"
: соответствие критериям *.txt-printf "%P"
: вывод относительного пути (страница руководства: «Имя файла с именем начальной точки, в которой он был найден, удалено»).-printf "%P\0"
: нулевой символ завершает относительный путь вывода| tar
: передать выходные данные следующей команде, которая здесь — tar--null
: указывает последующей--files-from
опции читать имена с нулевым завершением. Помните, что мы просилиfind
создать\0
выходные данные с нулевым завершением ( ) вместо обычных\n
выходных данных с завершением. Это сделано для того, чтобы охватить все возможные имена файлов с пробелами или другими специальными символами.--create
: создать файл tar. Равно-c
.--remove-files
: Я использую эту опцию для удаления файлов после их добавления в tarball. Вы можете удалить ее.--gzip
: gzip архив tarball. Равно-z
.--file="$HOME/my_txt.tar.gz"
: Выходной файл tarball, сжатый gzip. Равен-f "$HOME/my_txt.tar.gz"
--directory="$input_dir"
: Это означает, чтоtar
теперь изменяется на этот каталог. Теперь он будет искать имена файлов, которые передаются в этом каталоге (помните, что мы создали относительный путь имен файлов к этой папке). Равно-C "$input_dir"
.--files-from=/dev/stdin
: Его общая форма —--files-from=FILE
. Эта опция с опцией--null
указываетtar
, что имена вFILE
разделяются символом ASCII NULL вместо символа перевода строки (\n
). Мы также говорим, чтоFILE
isstdin
(передаетсяfind
напрямую из вtar
вместо чтения изFILE
на диске). Равно-T -
.
Некоторые из вышеперечисленных вариантов можно заменить на варианты с одним символом и объединить.
find "$input_dir" -maxdepth 1 -type f -name "*.txt" -printf "%P\0" | tar --null --remove-files -czf "$HOME/my_txt.tar.gz" -C "$input_dir" -T -
Вы можете проверить список файлов, используя опцию -t
или --list
:
tar -tf "$HOME/my_txt.tar.gz"
Теперь, чтобы извлечь файлы в каталог $output_dir (который существует), используйте это:
tar -xvzf "$HOME/my_txt.tar.gz" -C "$output_dir"
Опция v
является подробной, и вы также можете добавить ее во время создания tarball.
решение3
Ответ slhck не позволяет фильтровать нужные нам файлы и включает весь каталог, а подстановка shell не будет работать с этой опцией каталога (см. эту проблему, описанную здесь:Как заставить работать tar-глобалистику с опцией «изменить каталог»).
shaheen g ответ отличный, но нулевые байты не позволили мне использовать команду в языке программирования, потому что нулевые байты запрещены в строке. Поэтому я адаптировал его для работы без нулевых байтов, когда вам не нужно обрабатывать имена файлов с пробелами, ответздесь.
tar -czf /a/b/c.tar.gz -C /e/f/g $(find /e/f/g -maxdepth 1 -type f -name "*.txt" -printf "%f\n")
или
find /e/f/g -maxdepth 1 -type f -name "*.txt" -printf "%f\n" | tar -czf /a/b/c.tar.gz -C /e/f/g -T -