Linux 如何使用 xargs 复制名称中包含空格和引号的文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/143171/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I use xargs to copy files that have spaces and quotes in their names?
提问by Drew Stephens
I'm trying to copy a bunch of files below a directory and a number of the files have spaces and single-quotes in their names. When I try to string together find
and grep
with xargs
, I get the following error:
我正在尝试在目录下复制一堆文件,并且许多文件的名称中有空格和单引号。当我尝试将find
和串在一起grep
时xargs
,出现以下错误:
find .|grep "FooBar"|xargs -I{} cp "{}" ~/foo/bar
xargs: unterminated quote
Any suggestions for a more robust usage of xargs?
对更强大地使用 xargs 有什么建议吗?
This is on Mac OS X 10.5.3(Leopard) with BSD xargs
.
这是在带有 BSD 的Mac OS X 10.5.3(Leopard) 上xargs
。
采纳答案by godbyk
You can combine all of that into a single find
command:
您可以将所有这些组合成一个find
命令:
find . -iname "*foobar*" -exec cp -- "{}" ~/foo/bar \;
This will handle filenames and directories with spaces in them. You can use -name
to get case-sensitive results.
这将处理其中包含空格的文件名和目录。您可以使用-name
来获取区分大小写的结果。
Note: The --
flag passed to cp
prevents it from processing files starting with -
as options.
注意:--
传递给的标志cp
阻止它处理-
以选项开头的文件。
回答by Chris Jester-Young
find . -print0 | grep --null 'FooBar' | xargs -0 ...
find . -print0 | grep --null 'FooBar' | xargs -0 ...
I don't know about whether grep
supports --null
, nor whether xargs
supports -0
, on Leopard, but on GNU it's all good.
我不知道是否grep
支持--null
,是否也xargs
支持-0
,豹,但在GNU这一切都很好。
回答by Shannon Nelson
Look into using the --null commandline option for xargs with the -print0 option in find.
考虑在 find 中使用 xargs 的 --null 命令行选项和 -print0 选项。
回答by Tometzky
This is more efficient as it does not run "cp" multiple times:
这更有效,因为它不会多次运行“cp”:
find -name '*FooBar*' -print0 | xargs -0 cp -t ~/foo/bar
回答by Jonathan Leffler
Be aware that most of the options discussed in other answers are not standard on platforms that do not use the GNU utilities (Solaris, AIX, HP-UX, for instance). See the POSIXspecification for 'standard' xargs behaviour.
请注意,其他答案中讨论的大多数选项在不使用 GNU 实用程序(例如 Solaris、AIX、HP-UX)的平台上都不是标准的。有关“标准”xargs 行为,请参阅POSIX规范。
I also find the behaviour of xargs whereby it runs the command at least once, even with no input, to be a nuisance.
我还发现 xargs 的行为,即使没有输入,它也至少运行一次命令,这很麻烦。
I wrote my own private version of xargs (xargl) to deal with the problems of spaces in names (only newlines separate - though the 'find ... -print0' and 'xargs -0' combination is pretty neat given that file names cannot contain ASCII NUL '\0' characters. My xargl isn't as complete as it would need to be to be worth publishing - especially since GNU has facilities that are at least as good.
我编写了自己的 xargs (xargl) 私人版本来处理名称中的空格问题(只有换行符分开 - 尽管 'find ... -print0' 和 'xargs -0' 组合非常简洁,因为文件名不能包含 ASCII NUL '\0' 字符。我的 xargl 并不像值得发布的那样完整 - 特别是因为 GNU 具有至少同样好的设施。
回答by Jonathan Leffler
I have found that the following syntax works well for me.
我发现以下语法对我很有效。
find /usr/pcapps/ -mount -type f -size +1000000c | perl -lpe ' s{ }{\ }g ' | xargs ls -l | sort +4nr | head -200
In this example, I am looking for the largest 200 files over 1,000,000 bytes in the filesystem mounted at "/usr/pcapps".
在此示例中,我正在查找挂载在“/usr/pcapps”的文件系统中超过 1,000,000 字节的最大 200 个文件。
The Perl line-liner between "find" and "xargs" escapes/quotes each blank so "xargs" passes any filename with embedded blanks to "ls" as a single argument.
“find”和“xargs”之间的Perl line-liner转义/引用每个空格,因此“xargs”将任何带有嵌入空格的文件名作为单个参数传递给“ls”。
回答by Jonathan Leffler
bill_starr's Perl versionwon'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)...
bill_starr 的 Perl 版本不适用于嵌入的换行符(仅处理空格)。对于那些在例如 Solaris 上没有 GNU 工具的人来说,更完整的版本可能是(使用 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.
根据需要调整 find 和 grep 参数或其他命令,但 sed 将修复您嵌入的换行符/空格/制表符。
回答by Carl Yamamoto-Furst
I used Bill Star's answerslightly modified on Solaris:
我使用了Bill Star在 Solaris 上稍加修改的答案:
find . -mtime +2 | perl -pe 's{^}{\"};s{$}{\"}' > ~/output.file
This will put quotes around each line. I didn't use the '-l' option although it probably would help.
这将在每一行周围加上引号。我没有使用 '-l' 选项,尽管它可能会有所帮助。
The file list I was going though might have '-', but not newlines. I haven't used the output file with any other commands as I want to review what was found before I just start massively deleting them via xargs.
我要去的文件列表虽然可能有“-”,但没有换行符。我没有将输出文件与任何其他命令一起使用,因为我想在开始通过 xargs 大量删除它们之前查看发现的内容。
回答by mavit
find | perl -lne 'print quotemeta' | xargs ls -d
I believe that this will work reliably for any character except line-feed (and I suspect that if you've got line-feeds in your filenames, then you've got worse problems than this). It doesn't require GNU findutils, just Perl, so it should work pretty-much anywhere.
我相信这对于除换行符以外的任何字符都可以可靠地工作(我怀疑如果您的文件名中有换行符,那么您会遇到比这更糟糕的问题)。它不需要 GNU findutils,只需要 Perl,所以它几乎可以在任何地方工作。
回答by oyouareatubeo
I ran into the same problem. Here's how I solved it:
我遇到了同样的问题。这是我解决它的方法:
find . -name '*FoooBar*' | sed 's/.*/"&"/' | xargs cp ~/foo/bar
I used sed
to substitute each line of input with the same line, but surrounded by double quotes. From the sed
man page, "...An ampersand (``&'') appearing in the replacement is replaced by the string matching the RE..." -- in this case, .*
, the entire line.
我曾经sed
用同一行替换每一行输入,但用双引号括起来。在sed
手册页中,“ ...出现在替换中的与号 (``&'') 被与 RE... 匹配的字符串替换”——在这种情况下.*
,是整行。
This solves the xargs: unterminated quote
error.
这解决了xargs: unterminated quote
错误。