26

Команда find дает такой вывод:

[root@localhost /]# find var/log/ -iname anaconda.*
var/log/anaconda.log
var/log/anaconda.xlog
var/log/anaconda.yum.log
var/log/anaconda.syslog
var/log/anaconda.program.log
var/log/anaconda.storage.log

После объединения с tar он показывает следующий вывод:

[root@localhost /]# find var/log/ -iname anaconda.* -exec tar -cvf file.tar {} \;
var/log/anaconda.log
var/log/anaconda.xlog
var/log/anaconda.yum.log
var/log/anaconda.syslog
var/log/anaconda.program.log
var/log/anaconda.storage.log

Но при отображении файла tar он показывает только один файл

[root@localhost /]# tar -tvf file.tar
-rw------- root/root    208454 2012-02-27 12:01 var/log/anaconda.storage.log

Что я здесь не так делаю?

С xargs я получаю этот вывод:

[root @ localhost /] # find var /log / -iname anaconda. * | xargs tar -cvf file1.tar

Второй вопрос

Во время ввода / перед var, означает find /var/log почему он дает этот mesaage tar: удаление начального `/'из имен членов

[root@localhost /]# find /var/log/ -iname anaconda.* -exec tar -cvf file.tar {} \;
tar: Removing leading `/' from member names
/var/log/anaconda.log
tar: Removing leading `/' from member names
/var/log/anaconda.xlog
tar: Removing leading `/' from member names
/var/log/anaconda.yum.log
tar: Removing leading `/' from member names
/var/log/anaconda.syslog
tar: Removing leading `/' from member names
/var/log/anaconda.program.log
tar: Removing leading `/' from member names
/var/log/anaconda.storage.log

В простой форме, в чем разница между следующими двумя?

find var/log и find /var/log

6 ответов6

35

Обратите внимание, что find вызовет действие -exec для каждого найденного файла .

Если вы запускаете tar -cvf file.tar {} для каждого выходного файла find , это означает, что вы будете перезаписывать file.tar каждый раз, что объясняет, почему у вас остался один архив, содержащий только anaconda.storage.log - это последний файл find выходы.

Теперь вы действительно хотите добавлять файлы в архив, а не создавать их каждый раз (это то, что делает опция -c ). Итак, используйте следующее:

find var/log/ -iname "anaconda.*" -exec tar -rvf file.tar {} \;

Параметр -r добавляется в архив, а не создает его заново каждый раз.

Примечание. Замените -iname anaconda.* -iname "anaconda.*" . Звездочка является подстановочным знаком и может быть расширена вашей оболочкой, прежде чем find даже увидит его. Чтобы предотвратить это расширение, заключите аргумент в двойные кавычки.


Что касается удаления tar начале /: архив должен содержать только относительные имена файлов. Если вы добавили файлы с начальным / , они будут сохранены как абсолютные имена файлов, например, буквально означающие /var/… на вашем компьютере.

IIRC это просто предосторожность для реализаций tar отличных от GNU, и это безопаснее, потому что вы не будете перезаписывать ваши фактические данные в /var/… при извлечении архива, если он содержит относительные имена файлов.

33

Вы можете использовать что-то вроде:

find var/log -iname 'anaconda.*' -print0 | tar -cvf somefile.tar --null -T -

-print0 и -T работают вместе, чтобы разрешить имена файлов с пробелами, символами новой строки и т.д. Последний - указывает tar читать входные имена файлов из stdin.

Обратите внимание, что -print0 должен идти в конце вашего утверждения, согласно этому ответу. В противном случае вы, вероятно, получите больше файлов, чем ожидаете.

11

Попробуй это:

tar -cvf file.tar `find var/log/ -iname "anaconda.*"`

Вы пытались использовать find to -exec tar . Но, как работает опция -exec , она запускает эту команду один раз для каждого найденного файла, в результате чего tar каждый раз перезаписывает файл tar, который он создает. Вот почему вы только закончили с последним. Кроме того, вам нужно поместить кавычки вокруг указанного вами шаблона, чтобы find чтобы оболочка не раскрыла его перед передачей для find .

Используя подстановку команд обратными чертами (или, если хотите, нотацией $(...) ), весь список имен, созданных функцией find , вставляется обратно в командную строку в качестве аргументов для tar , заставляя его записывать их все сразу.

6

Вопрос 1

Ваша команда не выполняется, потому что tar берет каждый из найденных файлов и архивирует их в file.tar . Каждый раз, когда это происходит, он перезаписывает ранее созданный file.tar .

Если вам нужен один архив со всеми файлами, то просто запустите tar напрямую, вам не нужно find (и да, это работает для файлов с пробелами в их именах):

tar -vcf file.tar /var/log/anaconda*   

вопрос 2

Две команды совершенно разные:

  • find var/log будет искать каталог с именем var/log который является подкаталогом вашего текущего каталога, он эквивалентен find ./var/log (обратите внимание на ./).

  • find /var/log будет искать каталог /var/log который является подкаталогом корня, /.

Ведущий / сообщение от tar , not find . Это означает, что он удаляет первое / из ваших имен файлов, чтобы превратить абсолютные пути в относительные . Это означает, что файл из /var/log/anaconda.error будет извлечен в ./var/log/anaconda.error когда вы распакуете архив.

1

Я думаю, что использование -exec для каждого файла может сделать сжатие tar очень медленным, если у вас много файлов. Я предпочитаю использовать команду:

find . -iname "*.jpg" | cpio -ov -H tar -F jpgs.tar
1

Есть два способа, с помощью которых -exec может работать. Один способ запускает команду много раз - один раз для каждого файла; другой способ запускает команду один раз, включая все файлы в виде списка параметров.

  • -exec tar -cvf file.tar {} ';' запускает команду tar для каждого файла, каждый раз перезаписывая архив.
  • -exec tar -cvf file.tar {} '+' запускает команду tar один раз, создавая архив всех найденных файлов.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .