только файлы tar, без каталогов

16

Я, вероятно, могу написать сценарий оболочки только для поиска файлов, затем передать список в tar, но мне интересно, есть ли уже встроенная функция в tar, которая позволяет делать это только в одной командной строке?

Например, я нашел --no-recursionпереключатель, но когда я делаю:

tar --no-recursion -cvf mydir.tar mydir

Он только архивирует имена записей в каталоге (включая подкаталоги!), Но не архивирует файлы.

Я также попробовал:

 tar --no-recursion -cvf mydir.tar mydir/*

Но в то время как он архивирует только файлы, он также архивирует имена подкаталогов.

Есть ли способ указать только файлы tar, без каталогов?

ateiob
источник
5
Просто чтобы уточнить: вы хотите создать архив с «плоской» структурой (т.е. все файлы смешаны в одном каталоге)?
rozcietrzewiacz 18.11.11
1
Вы можете создать новый каталог find mydir -type f |xargs cp -t tempdirи затем tar tempdir.
Кевин
@rozcietrzewiacz Да, плоский, но только из этого каталога, а не из подкаталогов.
ateiob
1
Хорошо, я думаю, что вижу, что ты пытаешься сделать. Как насчетfind mydir -depth 1 -type f | xargs tar cf mydir.tar
Кевин
2
Ах, пробелы. Используйте ФАЙНД -exec вместо: find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +. В +путы все файлы на той же командной строке , как xargs.
Кевин

Ответы:

11

Как указывает camh, предыдущая команда имела небольшую проблему в том, что, учитывая слишком много имен файлов, она выполнялась более одного раза, а последующие вызовы молча стирали предыдущие запуски. Поскольку мы тоже не сжимаем, мы можем добавить вместо перезаписи:

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar Avf mydir.tar
find mydir -maxdepth 1 -type f -exec tar Avf mydir.tar {} +

Ответ Iocnarz в использования tar«s --nullи -Tпараметры работы , а также. Если вы cpioустановили, ответ Camh с его помощью тоже хорошо. И если у вас есть zshи не против использовать его для команды, ответ Жиля с использованием zsh glob ( *(.)) кажется наиболее простым.


Ключ был -maxdepthвариант. Окончательный ответ, относящийся к пробелам соответственно:

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar cvf mydir.tar

Это также должно работать:

find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +
Kevin
источник
4
Оба из них могут привести к нескольким вызовам tar. Как xargsи findс +вариантом имеет максимальное количество аргументов , которые могут быть переданы дегтем. Это приведет к тому, что второй вызов tar перезапишет вывод первого.
Camh
2
Расширяя предел xargs, xargs по умолчанию использует максимальную командную строку 128 КБ. Если список файлов больше, вы получаете второй (или более) вызов команды (tar), что приводит к потере данных без вывода сообщений. Вы можете использовать -xдля принудительного сбоя xargs вместо потери данных, и хотя это лучше, чем ошибка потери данных без вывода сообщений, она все же не идеальна. Эта ошибка сортировки очень опасна, потому что сначала все выглядит нормально, но со временем список файлов растет, вы начинаете его запускать и можете не заметить, пока не попытаетесь восстановить резервную копию. Тогда уже поздно.
Camh
@camh Ты прав, спасибо, что указал на это; Я обновил, чтобы отразить это.
Кевин
1
«Окончательный ответ» неверен, если вы используете «tar c» без -T, вы можете получить частичные результаты.
Eckes
14

Когда вы хотите использовать findс tar, лучший способ - использовать cpioвместо tar. cpioможет писать архивы tar и предназначен для получения списка файлов для архивирования из stdin.

find mydir -maxdepth 1 -type f -print0 | cpio -o -H ustar -0 > mydir.tar

Использование findи cpioявляется более unix-y подходом в том смысле, что вы позволяете findделать выбор файла со всей его мощью и cpioархивировать. Стоит научиться этому простому использованию cpio, так как вам легко решать проблемы, с которыми вы сталкиваетесь при попытке tar.

CAMH
источник
Brilliant! Я использовал cpio в далеком прошлом, но никогда не знал о варианте ustar.
Ян Макгоуэн
2
Это сработало для меня намного лучше, чем принятый ответ.
Дейл Андерсон
1
просто гнида -maxdepth 1 должен предшествовать -type f, иначе вы получите предупреждение от некоторых находок
kdubs,
Спасибо @kdubs. Я обновил ответ, чтобы поставить -maxdepthраньше -type.
Camh
3

Я не уверен, что понимаю ваши требования. Если вы хотите хранить обычные файлы в mydirподкаталогах, но не в их подкаталогах, самый простой способ - использовать zsh, где сопоставление только обычных файлов - простой вопрос использования . спецификатора glob :

tar cf mydir.tar mydir/*(.)
Жиль "ТАК - перестань быть злым"
источник
3

Вы можете даже использовать find ... -print0и tar ... --nullнапрямую, не используя xargsвообще.

find . -maxdepth 1 -type f -print0 | tar cvf mydir.tar --null -T -

В данном примере --no-recursionопция to tarне обязательна, потому что только пути файлов (а не каталогов) будут переданы из findв tar.

Однако использование --no-recursionопции to tarв следующем примере предотвращает tarдвойное архивирование каталогов. findбудет делать рекурсию дерева каталогов вместо tar.

# compare
find . -print0 | tar cf mydir.tar --null -T -
tar -tf mydir.tar | nl

find . -print0 | tar cf mydir.tar --null --no-recursion -T -
tar -tf mydir.tar | nl
locnarz
источник
2

Как man tarговорится во вступительном абзаце (последнее предложение),

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

Который я понимаю как «нет» ответ на ваш вопрос.

rozcietrzewiacz
источник
Хороший улов, за исключением того, что tar теперь включает в себя многочисленные механизмы исключения (например --no-recursion, --exclude-tagи т. Д.). Я смотрю на то, --exclude-tagчто выглядит многообещающе, но, кажется, является полной противоположностью того, что я ищу.
ateiob
Я попробовал это и увидел, как символы удаляются из длинных путей. Использование tar с -T и --null в качестве предложенного camh позволило избежать этой проблемы.
Пол Браннан,
1
star -c -C startdir -find . ! -type d > out.tar

Пропустите -C startdirи замените .на, startdirесли оно должно появиться в архиве.

Это наиболее эффективный метод, основанный на возможностях libfind. Libfind также предлагает основные цвета, -chown -chgrp -chmodкоторые изменяют struct stat и позволяют архивировать различные метаданные. Это также работает в режиме списка и извлечения и во многих случаях избавляет от необходимости извлекать весь архив.

Шили
источник
Можете ли вы использовать -findв -copyрежиме. Краткий обзор справочной страницы предполагает, что вы можете, но я не смог заставить его работать (пытаясь ответить на вопрос Как скопировать измененные файлы при сохранении структуры папок ) (с schily-2016-02-10)
Стефан Шазелас
Я не проверял это в течение более длительного времени. Возможно, в данный момент есть ошибка. Страница man говорит, что последним аргументом будет каталог извлечения, но когда я пытаюсь это сделать, я получаю: «Аргументы пути, которые еще не поддерживаются в режиме извлечения». Это то, что вы получаете, когда пытаетесь?
Шили
да. Страница man также говорит, что вы можете найти аргументы поиска только после -find, но если я помещу каталог назначения перед -find, я также получу ошибку
Стефан Шазелас
Существует код для отключения кода поиска в процессе извлечения, и сообщение об ошибке от неправильной проверки, которая ожидает -c, но также должна разрешать -copy. В режиме -copy анализатор поиска не должен включать последний аргумент.
Шили
1
Окончательное решение теперь опубликовано в инструментах schily по адресу sourceforge.net/projects/schilytools/files/schily-2016-03-11.tar.bz2, это также устраняет проблему из-за отсутствия setlocale () в star и позволяет - С директорией star -find.
Шили
0

Я мог бы найти решение.

find mydir -type f -printf '%P\0'|tar czvf mydir.tar.gz -C mydir --null -T -

Это может быть немного дорого, но в любом случае это будет работать, потому что это не зависит от xargs.

Ciel
источник
-1

dir = your_dir; CD $ DIR; tar -cvf file.tar `найти. -maxdepth 1-type f -print`

H Bosch
источник