Я пытаюсь скопировать кучу файлов в каталог, а в именах файлов есть пробелы и одинарные кавычки. Когда я пытаюсь связать вместе find
и grep
с xargs
, я получаю следующую ошибку:
find .|grep "FooBar"|xargs -I{} cp "{}" ~/foo/bar
xargs: unterminated quote
Любые предложения для более надежного использования xargs?
Это на Mac OS X 10.5.3 (Leopard) с BSD xargs
.
--delimiter
параметр (-d
). Попробуйте использовать его\n
в качестве разделителя. Это предотвращаетxargs
разделение строк с пробелами на несколько слов / аргументов.Ответы:
Вы можете объединить все это в одну
find
команду:Это будет обрабатывать имена файлов и каталогов с пробелами в них. Вы можете использовать
-name
для получения результатов с учетом регистра.Примечание. Переданный
--
флаг неcp
позволяет обрабатывать файлы, начиная с-
опций.источник
xargs
не менее, не обязателен для решения проблемы, которую вы описываете,find
уже поддерживает-exec
+
пунктуацию.find . -print0 | grep --null 'FooBar' | xargs -0 ...
Я не знаю,
grep
поддерживает ли--null
, илиxargs
поддерживает-0
, на Leopard, но на GNU это все хорошо.источник
grep -{z|Z}
означает «вести себя как zgrep» (распаковка), а не как «вывести нулевой байт после каждого имени файла». Используйтеgrep --null
для достижения последнего.find . -name 'FooBar' -print0 | xargs -0 ...
?-name
или-path
работает просто отлично. ОП указал использованиеgrep
, предположительно, потому что они хотят фильтровать список с помощью регулярных выражений.xargs -0
в сочетании сfind -print0
. Последний печатает имена файлов с терминатором NUL, а первый получает файлы таким образом. Зачем? Имена файлов в Unix могут содержать символы новой строки. Но они не могут содержать NUL-символов.Самый простой способ сделать то, что хочет оригинальный постер, это изменить разделитель с любого пробела на символ конца строки, например так:
источник
sed -e 's_\(.*\)_"\1"_g'
xargs
.xargs: illegal option -- d
Это более эффективно, так как не запускает "cp" несколько раз:
источник
Я столкнулся с той же проблемой. Вот как я это решил:
Раньше я
sed
заменял каждую строку ввода одной строкой, но в двойных кавычках. Наsed
странице руководства « ... амперсанд (` `& ''), появляющийся при замене, заменяется строкой, соответствующей RE ... " - в данном случае,.*
всей строкой.Это решает
xargs: unterminated quote
ошибку.источник
sed s/.*/\"&\"/
чтобы заставить его работать."
in - разве что sed также заключает в кавычки кавычки?sed
гениально и пока правильное решение без переписывания проблемы!Этот метод работает на Mac OS X v10.7.5 (Lion):
Я также проверил точный синтаксис, который вы разместили. Это также хорошо работало на 10.7.5.
источник
-I
подразумевает-L 1
(так говорит руководство), что означает, что команда cp выполняется один раз для файла = v slow.find ... -print0
иxargs -0
для работы Arround Xargs "по умолчанию кавычки являются специальными". Во-вторых, обычно используйте'{}'
не{}
в командах, передаваемых в xargs, для защиты от пробелов и специальных символов.Просто не используйте
xargs
. Это аккуратная программа, но она плохо сочетается сfind
когда сталкиваешься с нетривиальными случаями.Вот портативное решение (POSIX), то есть один , который не требует
find
,xargs
илиcp
расширения конкретных GNU:Обратите внимание на окончание
+
вместо более привычного;
.Это решение:
правильно обрабатывает файлы и каталоги со встроенными пробелами, символами новой строки или любыми экзотическими символами.
работает в любой системе Unix и Linux, даже в тех, которые не предоставляют инструментарий GNU.
не использует
xargs
хорошую и полезную программу, но требует слишком много настроек и нестандартных функций для правильной обработкиfind
вывода.также более эффективен (читай быстрее ), чем принятый, и большинство, если не все остальные ответы.
Также обратите внимание, что несмотря на то, что указано в некоторых других ответах или комментариях, цитирование
{}
бесполезно (если только вы не используете экзотическуюfish
оболочку).источник
find
может делать то, чтоxargs
делает без каких-либо накладных расходов.Рассмотрите использование параметра командной строки --null для xargs с параметром -print0 в find.
источник
Для тех, кто полагается на команды, кроме find, например
ls
:источник
-I
подразумевает-L 1
Я считаю, что это будет работать надежно для любого символа, кроме перевода строки (и я подозреваю, что если у вас есть перевод строки в именах файлов, то у вас проблемы хуже, чем этот). Он не требует GNU findutils, только Perl, поэтому он должен работать практически везде.
источник
mkdir test && cd test && perl -e 'open $fh, ">", "this-file-contains-a-\n-here"' && ls | od -tx1
|perl -lne 'print quotemeta'
это именно то, что я искал. Другие посты здесь не помогли мне, потому что вместо того, чтобыfind
мне приходилось использовать,grep -rl
чтобы значительно сократить количество PHP-файлов до только зараженных вредоносным ПО.Я обнаружил, что следующий синтаксис работает хорошо для меня.
В этом примере я ищу самые большие 200 файлов размером более 1 000 000 байтов в файловой системе, смонтированной в «/ usr / pcapps».
Линейная строка Perl между «find» и «xargs» экранирует / заключает в кавычки каждый пробел, поэтому «xargs» передает любое имя файла со встроенными пробелами в «ls» в качестве единственного аргумента.
источник
Задача фрейма - вы спрашиваете, как использовать xargs. Ответ таков: вы не используете xargs, потому что он вам не нужен.
Замечание
user80168
описывает способ сделать это непосредственно сП, без вызова ф для каждого файла:Это работает потому что:
cp -t
флаг позволяет дать целевой каталог ближе к началуcp
, а не ближе к концу. Отman cp
:--
Флаг говоритcp
интерпретировать все после того, как в качестве имени файла, а не флаг, поэтому файлы , начинающиеся с-
или--
не запутыватьcp
; это все еще нужно, потому что символы-
/--
интерпретируются какcp
, тогда как любые другие специальные символы интерпретируются оболочкой.find -exec command {} +
Вариант по существу , делает то же самое , как xargs. Отman find
:Используя это непосредственно в find, вы избегаете необходимости вызова канала или оболочки, так что вам не нужно беспокоиться о каких-либо неприятных символах в именах файлов.
источник
Помните, что большинство опций, обсуждаемых в других ответах, не являются стандартными на платформах, которые не используют утилиты GNU (например, Solaris, AIX, HP-UX). Смотрите спецификацию POSIX для «стандартного» поведения xargs.
Я также считаю, что поведение xargs, когда он запускает команду хотя бы один раз, даже без ввода, вызывает неудобства.
Я написал свою собственную частную версию xargs (xargl) для решения проблем с пробелами в именах (разделяются только новые строки - хотя комбинация 'find ... -print0' и 'xargs -0' довольно аккуратна, поскольку имена файлов не могут содержат символы ASCII NUL '\ 0'. Мой xargl не настолько полный, как того стоило бы публиковать, тем более что в GNU есть как минимум такие же хорошие возможности.
источник
find
не нуженxargs
(а это было уже 11 лет назад).С Bash (не POSIX) вы можете использовать подстановку процесса, чтобы получить текущую строку внутри переменной. Это позволяет вам использовать кавычки для экранирования специальных символов:
источник
Я пытался сделать что-то немного другое. Я хотел скопировать мои файлы .txt в мою папку TMP. Имена файлов .txt содержат пробелы и символы апострофа. Это сработало на моем Mac.
источник
Если версии find и xarg в вашей системе не поддерживают
-print0
и не-0
переключаются (например, AIX find и xargs), вы можете использовать этот ужасно выглядящий код:Здесь sed позаботится о выходе из пробелов и кавычек для xargs.
Проверено на AIX 5.3
источник
Я создал небольшой переносимый скрипт-обертку под названием «xargsL» вокруг «xargs», который решает большинство проблем.
В отличие от xargs, xargsL принимает одно имя пути на строку. Имена путей могут содержать любой символ, кроме (очевидно) символа новой строки или байтов NUL.
В списке файлов цитирование не допускается и не поддерживается - имена файлов могут содержать все виды пробелов, обратных косых черт, обратных черт, подстановочных знаков оболочки и т. П. - xargsL будет обрабатывать их как буквенные символы, без вреда для себя.
Как дополнительная бонусная функция, xargsL не будет запускать команду один раз, если нет ввода!
Обратите внимание на разницу:
Все аргументы, переданные xargsL, будут переданы xargs.
Вот сценарий оболочки POSIX "xargsL":
Поместите скрипт в какой-то каталог в вашем $ PATH и не забудьте
$ chmod +x xargsL
сценарий, чтобы сделать его исполняемым.
источник
Perl-версия bill_starr не будет хорошо работать для встроенных символов новой строки (справляется только с пробелами). Например, для Solaris, где у вас нет инструментов GNU, может быть более полная версия (с использованием sed) ...
настройте аргументы find и grep или другие команды, как вам требуется, но sed исправит ваши встроенные символы новой строки / пробелов / табуляции.
источник
Я использовал ответ Билла Стар, слегка измененный на Solaris:
Это поместит кавычки вокруг каждой строки. Я не использовал опцию '-l', хотя это, вероятно, помогло бы.
Список файлов, который я собирался, хотя мог иметь «-», но не переводы строк. Я не использовал выходной файл с какими-либо другими командами, так как хочу просмотреть то, что было найдено, прежде чем я просто начну массово удалять их с помощью xargs.
источник
Я немного поиграл с этим, начал размышлять над модификацией xargs и понял, что для случая использования, о котором мы здесь говорим, простая переопределение в Python - лучшая идея.
Во-первых, наличие ~ 80 строк кода для всего этого означает, что легко понять, что происходит, и если требуется другое поведение, вы можете просто взломать его в новый скрипт за меньшее время, чем требуется, чтобы получить ответ на что-то вроде переполнения стека.
См. Https://github.com/johnallsup/jda-misc-scripts/blob/master/yargs и https://github.com/johnallsup/jda-misc-scripts/blob/master/zargs.py .
С написанным yargs (и установленным Python 3) вы можете набрать:
сделать копирование 203 файлов одновременно. (Здесь 203, конечно, просто заполнитель, и использование странного числа, такого как 203, дает понять, что это число не имеет другого значения.)
Если вы действительно хотите что-то быстрее и без использования Python, возьмите zargs и yargs в качестве прототипов и перепишите их на C ++ или C.
источник
Вам может понадобиться grep каталог Foobar, например:
источник
-i
устарела и-I
должна использоваться вместо.Если вы используете Bash, вы можете преобразовать стандартный вывод в массив строк
mapfile
:Преимущества:
Вы можете добавить другие аргументы к именам файлов. Для
cp
, вы также можете:однако некоторые команды не имеют такой функции.
Недостатки:
Ну ... кто знает, доступен ли Bash на OS X?
источник