фильтр в "find" игнорируется, когда вывод передается в tar

фильтр в "find" игнорируется, когда вывод передается в tar

У меня следующая структура каталогов:

test/
test/1/
test/foo2bar/
test/3/

Я хочу сжать каталог "test", исключив все, что находится в подкаталогах (глубина не предопределена), которые включают строки "1" или "2". В оболочке bash я хочу использоватьнаходитьи передать его выводсмола. Я сначала тестируюнаходить:

find test/ -not -path "*1*" -not -path "*2*"

Выход:

test/
test/3

Отлично. Поэтому я объединяю это ссмола:

find test/ -not -path "*1*" -not -path "*2*" | tar -czvf test.tar.gz --files-from -

Выход:

test/
test/3/
test/1/
test/foo2bar/
test/3/

Действительно, в архиве присутствуют и «test/1», и «test/foo2bar».Почему эти аргументы были переданы tar, если они не должны были присутствовать в выводе find?

решение1

Чтобы расширить то, что сказал @cuonglm, tarпо умолчанию работает рекурсивно. Если вы передадите ему имя каталога, он заархивируетсодержаниеэтого каталога.

Вы можете изменить findкоманду так, чтобы она возвращала только имена файлов, а не каталогов...

find test/ -type f -not -path "*1*" -not -path "*2*" |
tar -czvf test.tar.gz --files-from -

Вместо этого вы можете использовать --no-recursionфлаг для tar:

find test/ -not -path "*1*" -not -path "*2*" | 
tar -czvf test.tar.gz --no-recursion --files-from - 

Что приводит к:

test/
test/3/

Флаг --no-recursionспецифичен для GNU tar. Если вы используете что-то другое, обратитесь к соответствующей странице руководства, чтобы узнать, доступна ли похожая функция.

Обратите внимание, что ваша findкоманда исключитфайлыкоторые содержат 1или 2в пути, а также в каталогах.

решение2

С помощью GNU tar вы также можете использовать --excludeопцию исключения файлов по именам.

$ tar --exclude "*1*" --exclude "*2*" -cvf foo.tar  test/
test/
test/3/

Также есть -Xили --exclude-from, который берет файл, из которого считываются шаблоны исключений.


Хотя find -not -path "*1*", это также исключит файлы, имена которых содержат 1или 2. Чтобы пропустить толькокаталогичьи имена соответствуют шаблону, используйте find -pruneи tar --no-recursion:

$ touch test/3/blah.1
$ find test/ -type d \( -name "*1*" -o -name "*2*" \) -prune -o -print |
   tar cvf test.tar --files-from - --no-recursion
test/
test/3/
test/3/blah.1

(По крайней мере, GNU tar и FreeBSD tar имеют --no-recursion)

Связанный контент