лише файли tar, відсутні каталоги


16

Можливо, я можу написати сценарій оболонки, щоб знайти лише файли, а потім передати список tar, але мені цікаво, чи вже є вбудована функція tar, яка дозволяє робити саме це в одному командному рядку?

Наприклад, я знайшов --no-recursionвимикач, але коли це роблю:

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

Він архівує лише імена записів у каталозі (включаючи підкаталоги!), Але не архівує жодних файлів.

Я також спробував:

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

Але хоча він архівує лише файли, він також архівує імена підкаталогів.

Чи є спосіб розповісти лише файли tar, не маючи каталогів?


5
Просто для уточнення: чи хочете ви створити архів із "плоскою" структурою (тобто всі файли, змішані в одному каталозі)?
rozcietrzewiacz

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

Як зазначає Кемх, попередня команда мала невелику проблему в тому, що даючи занадто багато імен файлів, вона виконувалася б не один раз, з пізнішими викликами мовчки витираючи попередні запуски. Оскільки ми також не стискаємо, ми можемо додавати замість перезапису:

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

Відповідь Іонарца на використання tar' --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 {} +

4
Це може призвести до декількох викликів tar. І в xargsі findз +варіантом є максимальна кількість аргументів, які можна передавати в tar. Це призведе до другого виклику дьогтю, що замінить вихід першого.
кем

2
Розширюючись на ліміт xargs, xargs за замовчуванням до максимуму 128KiB командного рядка. Якщо список файлів більший, ви отримуєте друге (або більше) виклик команди (tar), що призводить до безшумної втрати даних. Ви можете використовувати, -xщоб змусити xargs вийти з ладу замість втрати даних, і хоча це краще, ніж тиха помилка втрати даних, вона все ще не є ідеальною. Помилка такого роду настільки небезпечна, оскільки спочатку все здається нормально, але, оскільки список файлів з часом зростає, ви починаєте його запускати і, можливо, не помітите, поки не спробуєте відновити резервну копію. Тоді вже пізно.
кем

@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є більш універсальним підходом у тому, що ви дозволяєте findробити вибір файлів усією потужністю, яку він має, і дозволяєте cpioархівувати. Варто навчитися цьому простому використанню cpio, оскільки вам легко вирішити проблеми, перед якими ви намагаєтеся натрапити, намагаючись tar.


Блискуче! Я використовував cpio в далекому минулому, але ніколи не знав про варіант устару.
Ian McGowan

2
Це працювало для мене набагато краще, ніж прийнята відповідь.
Дейл Андерсон

1
просто ніт. -maxdepth 1 має прийти до -типу f або ви отримаєте попередження від деяких знахідок
kdubs

Дякую @kdubs. Я оновив відповідь, яку виклав -maxdepthраніше -type.
camh

3

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

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опція до tarне потрібна, оскільки тільки до контурів файлів (а не каталогів) будуть передані від findдо tar.

Однак використання --no-recursionпараметра 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

2

Як man tarговориться у вступному пункті (останнє речення),

Використання імені каталогу завжди означає, що підкаталоги нижче повинні бути включені до архіву.

Що я розумію як "ні" відповідь на ваше запитання.


Хороший улов, за винятком того, що смола тепер включає в себе численні винятки meachisms (наприклад --no-recursion, --exclude-tagі т.д.). Я дивлюся на те, --exclude-tagщо виглядає багатообіцяюче, але, здається, абсолютно протилежне тому, що я шукаю.
ateiob

Я спробував це, і побачив, як символи видаляються з довгих імен. Використання смоли з -T та --null як запропоновано camh уникло цієї проблеми.
Пол Браннан

1
star -c -C startdir -find . ! -type d > out.tar

Опустити -C startdirі замінити .з , startdirякщо він повинен з'явитися в архіві.

Це найбільш ефективний метод, заснований на особливостях лібфінду. Libfind також пропонує праймери, -chown -chgrp -chmodякі змінюють структуру stat на місці та дозволяють архівувати різні метадані. Це також працює в режимі списку та вилучення та уникає необхідності витягувати весь архів у багатьох випадках.


Чи можна використовувати -findв -copyрежимі. Конспект сторінки чоловічої сторінки пропонує, що ви можете, але мені не вдалося змусити його працювати (намагаючись відповісти, як скопіювати модифіковані файли, зберігаючи структуру папок ) (зі схилією 2016-02-10)
Stéphane Chazelas

Я довго не тестував цього. Можливо, на даний момент є помилка. Сторінка man говорить про те, що останнім аргументом буде каталог добування, але коли я спробую це, я отримую: "Аргументи шляху ще не підтримуються в режимі вилучення". Це те, що отримуєш, намагаючись?
schily

так. Сторінка man також говорить, що ви можете знайти аргументи лише після -find, але якщо я поставлю каталог призначення раніше -find, я також отримаю помилку
Stéphane Chazelas

Існує код для відключення коду пошуку в процесі вилучення, а повідомлення про помилку - від неправильної перевірки, яка очікує -c, але також повинна дозволяти -copy. У режимі -копіювання аналізатор пошуку не повинен включати останній аргумент.
schily

1
Остаточне рішення тепер було опубліковано в інструментах schily на sourceforge.net/projects/schilytools/files/schily-2016-03-11.tar.bz2, це також виправляє проблему зниклого setlocale () у зірці, і це дозволяє - C дирекція для star -find.
schily

0

Я, можливо, знайшов рішення.

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

Це може бути дорого коштувати, але все одно воно буде працювати, оскільки це не залежить від xargs.


-1

dir = your_dir; cd $ dir; tar -cvf file.tar `знайти. -maxdepth 1 -тип f -принт`

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.