我正在尝试复制一个目录下的一堆文件,其中一些文件名中有空格和单引号。 当我尝试使用find
,grep
和xargs
一起运行时,我会得到以下错误:
find .|grep "FooBar"|xargs -I{} cp "{}" ~/foo/bar
xargs: unterminated quote
有没有更加强大的使用 xargs
的建议?
我是在使用 BSD 版本的 xargs
,系统为 Mac OS X 10.5.3(Leopard)。
我正在尝试复制一个目录下的一堆文件,其中一些文件名中有空格和单引号。 当我尝试使用find
,grep
和xargs
一起运行时,我会得到以下错误:
find .|grep "FooBar"|xargs -I{} cp "{}" ~/foo/bar
xargs: unterminated quote
有没有更加强大的使用 xargs
的建议?
我是在使用 BSD 版本的 xargs
,系统为 Mac OS X 10.5.3(Leopard)。
您可以将所有内容组合到单个find
命令中:
find . -iname "*foobar*" -exec cp -- "{}" ~/foo/bar \;
这将处理包含空格的文件名和目录。您可以使用-name
选项获取区分大小写的结果。
注意:传递给cp
的--
标志可以防止其将以-
开头的文件视为选项进行处理。
find . -print0 | grep --null 'FooBar' | xargs -0 ...
这个命令会在当前目录下找到所有包含'FooBar'的文件,并将它们传递给后面的命令进行处理。 grep
和 xargs
都支持--null
和-0
参数,但我不确定 Leopard 系统是否支持该参数,不过在GNU系统中是可以使用的。
grep -{z|Z}
的意思是“表现得像zgrep”(解压缩),而不是预期的“在每个文件名后打印一个零字节”。使用grep --null
来实现后者。 - bassimfind . -name 'FooBar' -print0 | xargs -0 ...
这个命令有什么问题? - Quentin Pradetgrep
,可能是因为他们想使用正则表达式过滤列表。 - C. K. Youngxargs -0
与 find -print0
结合的原因。后者会打印带有 NUL 终止符的文件名,前者以这种方式接收文件。为什么?Unix 中的文件名可以包含换行符,但不能包含 NUL 字符。 - C. K. Young实现原帖所需的最简单方法是将分隔符从任何空格更改为仅使用行末字符,如下所示:
find whatever ... | xargs -d "\n" cp -t /var/tmp
sed -e 's_\(.*\)_"\1"_g'
命令,在文件名周围强制添加引号。 - ishahakxargs
。 - Mohammad Alhashashfind -name '*FooBar*' -print0 | xargs -0 cp -t ~/foo/bar
我遇到了同样的问题。这是我解决它的方式:
find . -name '*FoooBar*' | sed 's/.*/"&"/' | xargs cp ~/foo/bar
我使用了sed
命令来将输入的每一行替换为相同的行,但是用双引号括起来。从sed
的手册中可以看到:" ...在替换字符串中出现的 & 符号将被替换为与正则表达式相匹配的字符串..." -- 在这个例子中,是指整行,即.*
。
这解决了xargs: unterminated quote
错误。
sed s/.*/\"&\"/
命令才能使它正常工作。 - Pat"
的文件名 - 除非 sed 也引用引号? - artfulrobotsed
是巧妙的解决方案,而且不需要重新编写问题! - entonio这种方法适用于Mac OS X v10.7.5(狮子):
find . | grep FooBar | xargs -I{} cp {} ~/foo/bar
我也测试了您发布的确切语法。在10.7.5上也能正常工作。
-I
隐含了 -L 1
,也就是说 cp 命令会针对每个文件执行一次,速度非常慢。 - artfulrobotfind ... -print0
和xargs -0
来解决xargs的“默认引号是特殊字符”的问题。其次,在传递给xargs的命令中通常使用'{}'
而不是{}
来保护空格和特殊字符。 - Andreas Spindlerxargs -0 -J % cp -v % /foo/bar
- Phlogi不要使用xargs
。它是一个很好的程序,但在处理非常规情况时与find
不兼容。
这里有一个便携式(POSIX)解决方案,即不需要find
、xargs
或cp
GNU特定扩展:
find . -name "*FooBar*" -exec sh -c 'cp -- "$@" ~/foo/bar' sh {} +
注意这里的结尾使用 +
而不是更常见的 ;
。
该解决方案:
可以正确地处理嵌入空格、换行符或其他特殊字符的文件和目录。
适用于任何Unix和Linux系统,即使没有提供GNU工具包。
不使用xargs
,这是一个很好而且有用的程序,但需要太多调整和非标准功能才能正确处理find
的输出。
与已接受的答案和大部分甚至所有其他答案相比,也更有效率(读作更快)。
还要注意,尽管其他回复或评论中引用了 {}
,但它是无用的(除非您使用奇特的 fish
shell)。
find
可以在没有任何开销的情况下完成xargs
所做的工作。 - jlliagre对于那些依赖命令而不是find
的人:
find . | grep "FooBar" | tr \\n \\0 | xargs -0 -I{} cp "{}" ~/foo/bar
建议使用find命令的-print0选项,并与xargs命令的--null选项一起使用。
find | perl -lne 'print quotemeta' | xargs ls -d
mkdir test && cd test && perl -e 'open $fh, ">", "this-file-contains-a-\n-here"' && ls | od -tx1
- mavit|perl -lne 'print quotemeta'
正是我一直在寻找的。这里的其他帖子并没有帮助我,因为我需要使用 grep -rl
而不是 find
来大大减少 PHP 文件的数量,只留下有恶意软件的文件。 - Marcos
--delimiter
选项(-d
)。尝试使用\n
作为分隔符,这可以防止xargs
将带空格的行分隔成多个单词/参数。 - MattBianco