Как я могу использовать xargs для копирования файлов, которые имеют пробелы и кавычки на их имена?

225
задан Peter Mortensen 29 July 2018 в 10:28
поделиться

8 ответов

Можно объединить все это в сингл find команда:

find . -iname "*foobar*" -exec cp -- "{}" ~/foo/bar \;

Это обработает имена файлов и каталоги с пробелами в них. Можно использовать -name для получения чувствительных к регистру результатов.

Примечание: Эти -- флаг передал cp, препятствует тому, чтобы он обработал файлы, запускающиеся с - как опции.

196
ответ дан godbyk 23 November 2019 в 03:53
поделиться

Знайте, что большинство опций, обсужденных в других ответах, не является стандартным на платформах, которые не используют утилиты GNU (Солярис, AIX, HP-UX, например). Посмотрите спецификация POSIX для 'стандарта' xargs поведение.

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

я записал свою собственную частную версию xargs (xargl) для контакта с проблемами пробелов на имена (только отдельные новые строки - хотя 'находят...-print0' и 'xargs-0' комбинаций довольно аккуратен, учитывая, что имена файлов не могут содержать ASCII NUL '\0' символов. Мой xargl не так завершен, как это должно было бы быть должно стоить опубликовать - тем более, что GNU имеет средства, которые являются, по крайней мере, как хорошие.

2
ответ дан Jonathan Leffler 23 November 2019 в 03:53
поделиться

Изучите использование - пустой параметр командной строки для xargs с-print0 опцией в находке.

8
ответ дан Shannon Nelson 23 November 2019 в 03:53
поделиться

Это более эффективно, поскольку это не выполняет "CP" многократно:

find -name '*FooBar*' -print0 | xargs -0 cp -t ~/foo/bar
70
ответ дан Tometzky 23 November 2019 в 03:53
поделиться

find . -print0 | grep --null 'FooBar' | xargs -0 ...

я не знаю о том, является ли grep поддержки --null, ни ли xargs поддержки -0, на Leopard, но на GNU это всей пользой.

114
ответ дан James McMahon 23 November 2019 в 03:53
поделиться

Я нашел, что следующий синтаксис работает хорошо на меня.

find /usr/pcapps/ -mount -type f -size +1000000c | perl -lpe ' s{ }{\\ }g ' | xargs ls -l | sort +4nr | head -200

В этом примере, я ищу самые большие 200 файлов более чем 1 000 000 байтов в файловой системе, смонтированной в "/usr/pcapps".

лайнер строки Perl между "находкой" и "xargs" выходит/заключает из каждого пробела в кавычки, таким образом, "xargs" передает любое имя файла со встроенными пробелами к "ls" как отдельный аргумент.

5
ответ дан Peter Mortensen 23 November 2019 в 03:53
поделиться

Проблема с фреймом - вы спрашиваете, как использовать xargs. Ответ таков: вы не используете xargs, потому что он вам не нужен.

Комментарий от user80168 описывает способ сделать это напрямую с cp, без вызова cp для каждого файла:

find . -name '*FooBar*' -exec cp -t /tmp -- {} +

Это работает, потому что:

  • флаг cp -t позволяет задать целевой каталог ближе к началу cp, а не к концу. Из man cp:
   -t, --target-directory=DIRECTORY
         copy all SOURCE arguments into DIRECTORY
  • Флаг -- говорит cp интерпретировать все после как имя файла, а не флаг, поэтому файлы, начинающиеся с - или --, не путают cp; вам все еще нужно это, потому что символы - / -- интерпретируются как cp, тогда как любые другие специальные символы интерпретируются оболочкой.

  • Вариант find -exec command {} + по существу делает то же самое, что и xargs. Из man find:

   -exec command {} +                                                     
         This  variant  of the -exec action runs the specified command on
         the selected files, but the command line is built  by  appending
         each  selected file name at the end; the total number of invoca‐
         matched  files.   The command line is built in much the same way
         that xargs builds its command lines.  Only one instance of  `{}'
         is  allowed  within the command, and (when find is being invoked
         from a shell) it should be quoted (for example, '{}') to protect
         it  from  interpretation  by shells.  The command is executed in
         the starting directory.  If any invocation  returns  a  non-zero
         value  as exit status, then find returns a non-zero exit status.
         If find encounters an error, this can sometimes cause an immedi‐
         ate  exit, so some pending commands may not be run at all.  This
         variant of -exec always returns true.

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

1
ответ дан 23 November 2019 в 03:53
поделиться

bill_starr's Perl version won't work well for embedded newlines (only copes with spaces). For those on e.g. Solaris where you don't have the GNU tools, a more complete version might be (using sed)...

find -type f | sed 's/./\\&/g' | xargs grep string_to_find

adjust the find and grep arguments or other commands as you require, but the sed will fix your embedded newlines/spaces/tabs.

1
ответ дан 23 November 2019 в 03:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: