Несколько команд с find и xargs, в том числе с учетом специальных символов

В OS X я пытаюсь объединить следующие две команды в одну команду в сценарии bash, чтобы find работал только один раз. Файлы, используемые find, содержат пробелы и специальные символы.

Команда 1:

find /path -print0 | tr '\n' '\0' | xargs -0 chmod -N

Команда 2:

find /path -print0 | tr '\n' '\0' | xargs -0 xattr -c

Обе указанные выше команды работают.

Я понимаю из Заставить xargs выполнить команду один раз для каждой строки ввода ', что несколько команд могут быть выполнены через xargs с чем-то вроде

find /path -print0 | xargs -0 -I '{}' sh -c 'command1 {} ; command2 {}'

Однако моя попытка объединить команды с

find /path -print0 | tr '\n' '\0' | xargs -0 -I '{}' sh -c 'chmod -N {} ; xattr -c {}'

приводит к множественным ошибкам для каждого файла и папки в /path, например

chmod: Failed to clear ACL on file {}: No such file or directory
xattr: No such file: {}
sh: -c: line 0: syntax error near unexpected token `('

Кто-нибудь может помочь? Заранее спасибо.


person shineDR    schedule 07.06.2015    source источник
comment
Если ответ решит вашу проблему, примите его, нажав на большую галочку (✓) рядом с ним. Если вы нашли другие ответы полезными, проголосуйте за них. Принятие и голосование ответов помогает не только тем, кто ответил, но и будущим читателям. См. соответствующую статью справочного центра. Если на ваш вопрос еще нет полного ответа, оставьте отзыв.   -  person mklement0    schedule 28.01.2016


Ответы (1)


Попробуйте следующее:

find /path -exec sh -c 'chmod -N "$@"; xattr -c "$@"' - {} +
  • -exec ... +, передает (обычно) все подходящие пути указанной команде, что является их наиболее эффективным подходом.

    • Оба chmod и xattr поддерживают несколько файловых операндов, поэтому такой подход возможен.

    • find правильно сохраняет границы аргументов при передаче, заменяющей пути на {}, поэтому он будет правильно обрабатывать имена файлов со встроенными символами новой строки.
      Между прочим: я не понимаю, какова цель tr '\n', '\0' в вашем коде, учитывая, что вы уже выводят пути, разделенные \0, благодаря -print0.

  • Обратите внимание на - как на первый (фиктивный) аргумент, переданный в sh -c, потому что первый аргумент станет $0.


Что касается проблемы с вашей исходной командой:

Я не могу объяснить конкретные симптомы, но одна проблема заключается в том, что вы не цитируете экземпляры {} внутри своей команды оболочки, что делает их подверженными разбиению по словам (разбивает пути к файлам со встроенными пробелами на несколько аргументов).

person mklement0    schedule 23.12.2015
comment
Разве это не должно быть -exec bash вместо -exec sh, просто чтобы быть явным (OP использует bash)? - person Sumit; 23.12.2015
comment
@Sumit: исходная команда OP использует sh, поэтому я придерживался его. На практике, учитывая конкретную команду, это не имеет значения. Это не имело бы значения даже на других платформах, учитывая, что вся команда полностью совместима с POSIX. - person mklement0; 23.12.2015