如何使用xargs的复制具有在其名称空间和报价文件?如何使用xargs的复制具有在其名称空间和报价文

2019-05-12 16:02发布

我想一堆文件复制一个目录下面和一些文件的名称中包含空格和单引号。 当我尝试串起来, findgrepxargs ,我得到以下错误:

find .|grep "FooBar"|xargs -I{} cp "{}" ~/foo/bar
xargs: unterminated quote

对于xargs的更强大的使用有什么建议?

这是对的Mac OS X 10.5.3 (豹)与BSD xargs

Answer 1:

您可以将所有这一切到一个单一的find命令:

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

这将处理文件名和目录在其中的空间。 您可以使用-name得到区分大小写的结果。

注: --传递给标志cp阻止它处理的文件的开头-作为选项。



Answer 2:

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

我不知道是否grep支持--null ,也不是否xargs支持-0 ,在豹,但在GNU这一切都很好。



Answer 3:

做原来的海报想要什么的最简单方法是分隔符从任何空白刚刚结束的行字符这样的改变:

find whatever ... | xargs -d "\n" cp -t /var/tmp


Answer 4:

这是更有效,因为它不运行“CP”多次:

find -name '*FooBar*' -print0 | xargs -0 cp -t ~/foo/bar


Answer 5:

我遇到了同样的问题。 下面是我如何解决它:

find . -name '*FoooBar*' | sed 's/.*/"&"/' | xargs cp ~/foo/bar

我用sed替代输入的每一行具有相同的线,而是由双引号所包围。 从sed手册页,“...符号(``&‘’)出现在置换通过匹配RE ...字符串替换 ” -在这种情况下, .* ,整条生产线。

这解决了xargs: unterminated quote错误。



Answer 6:

此方法适用于Mac OS X的v10.7.5 (狮子):

find . | grep FooBar | xargs -I{} cp {} ~/foo/bar

我还测试您发布确切的语法。 这也对10.7.5正常工作。



Answer 7:

只要不使用xargs 。 这是一个整洁的程序,但它不顺利find ,当面对不平凡的案件。

这里是一个便携式(POSIX)的解决方案,即一个不需要findxargscp GNU特定的扩展:

find . -name "*FooBar*" -exec sh -c 'cp -- "$@" ~/foo/bar' sh {} +

注意结局+ ,而不是更常见的;

该解决方案:

  • 正确处理文件和目录与嵌入的空格,换行或任何稀奇古怪的字符。

  • 可在任何Unix和Linux系统上,即使是那些不提供GNU工具包。

  • 不使用xargs这是一个很好的和有用的程序,但需要太多的调整和非标准的功能,妥善处理find的输出。

  • 更有效 (读取速度更快 ),比公认的最如果不是所有其他的答案。

还需要注意的是,尽管什么在其他一些回复或评论引述说{}是无用的(除非您使用的是异国情调的fish贝)。



Answer 8:

考虑使用--null命令行选项,在找到-print0选项xargs的。



Answer 9:

对于那些谁依靠命令,比发现,如其他ls

find . | grep "FooBar" | tr \\n \\0 | xargs -0 -I{} cp "{}" ~/foo/bar


Answer 10:

find | perl -lne 'print quotemeta' | xargs ls -d

我相信,这将可靠地工作,除了换行符的任何字符(我怀疑,如果你已经在你的文件名了线的饲料,那么你有更严重的问题比这个)。 它不需要GNU的findutils,只是Perl的,所以它应该工作非常-很多的任何地方。



Answer 11:

我发现下面的语法很适合我。

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

在这个例子中,我在上安装在“的/ usr / pcapps”文件系统1,000,000字节寻找最大的200个文件。

之间的“发现”和“xargs的” Perl的线衬垫逃逸/援引每个坯料所以“xargs的”经过任何文件名以嵌入的空格为“LS”作为单个参数。



Answer 12:

要知道,大多数在其他的答案中讨论的选项是不是不使用GNU工具(的Solaris,AIX,HP-UX,例如)平台的标准。 见POSIX的“标准” xargs的行为规范。

我也发现xargs的行为,由此它运行的命令至少一次,甚至没有任何投入,造成滋扰。

我写的xargs我自己的私人版本(xargl)来处理的空格名字(只换行分开的问题 - 尽管“发现... -print0”和“xargs的-0”的组合是相当整洁,因为文件名不能包含ASCII NUL“\ 0”的角色我xargl的并不完整,因为它需要是值得出版 - 尤其是GNU有设施,至少一样好。



Answer 13:

对于我来说,我试图做的东西有点不同。 我想我的.txt文件复制到我的TMP文件夹中。 该.TXT文件名包含空格和撇号字符。 这个工作我的Mac上。

$ find . -type f -name '*.txt' | sed 's/'"'"'/\'"'"'/g' | sed 's/.*/"&"/'  | xargs -I{} cp -v {} ./tmp/


Answer 14:

如果发现你的系统上xarg版本不支持-print0-0开关(例如AIX查找和xargs的),你可以用这个非常期待的代码:

 find . -name "*foo*" | sed -e "s/'/\\\'/g" -e 's/"/\\"/g' -e 's/ /\\ /g' | xargs cp /your/dest

这里的sed会采取逃避的xargs的空间和报价的照顾。

测试在AIX 5.3



Answer 15:

我创建了一个名为“xargsL”绕“xargs的”小型便携式包装脚本其中涉及的问题最多。

相反,xargs的,xargsL接受每行一个路径名。 路径名可以包含除(明显)换行或NUL字节的任何字符。

无报价被允许在文件列表支持 - 您的文件名称可以包含各种空格,反斜杠,反引号,外壳通配符和类似的 - xargsL将处理它们作为文字字符,又何妨呢。

作为额外的奖励功能,如果没有输入xargsL将无法运行该命令一次!

注意区别:

$ true | xargs echo no data
no data

$ true | xargsL echo no data # No output

给xargsL任何参数将传递给xargs的。

这里是“xargsL” POSIX shell脚本:

 #! /bin/sh # Line-based version of "xargs" (one pathname per line which may contain any # amount of whitespace except for newlines) with the added bonus feature that # it will not execute the command if the input file is empty. # # Version 2018.76.3 # # Copyright (c) 2018 Guenther Brunthaler. All rights reserved. # # This script is free software. # Distribution is permitted under the terms of the GPLv3. set -e trap 'test $? = 0 || echo "$0 failed!" >& 2' 0 if IFS= read -r first then { printf '%s\n' "$first" cat } | sed 's/./\\&/g' | xargs ${1+"$@"} fi 

把脚本到某个目录在$ PATH,不要忘了

$ chmod +x xargsL

有脚本,使其可执行。



Answer 16:

bill_starr的Perl版本不会为嵌入式换行符工作得很好(只用空格科佩斯)。 对于那些如的Solaris,你没有GNU工具,更完整的版本可能(使用SED)...

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

调整的发现和grep参数或其他命令,根据您的需要,但sed的将解决您的嵌入式换行符/位/制表符。



Answer 17:

我用比尔星的回答在Solaris上稍作修改:

find . -mtime +2 | perl -pe 's{^}{\"};s{$}{\"}' > ~/output.file

这将使报价在每行。 我没有使用“-l”选项,虽然它可能会有所帮助。

文件列表我去,虽然可能有“ - ”,但不换行。 我想回顾一下被发现之前,我刚开始通过xargs的大量删除它们我还没有与任何其他命令使用的输出文件。



Answer 18:

使用bash(未POSIX),可以使用进程替换来获取变量中当前行。 这使您可以使用引号特殊字符进行转义:

while read line ; do cp "$line" ~/bar ; done < <(find . | grep foo)


Answer 19:

我打了这一点,开始考虑修改xargs的,并且意识到,那种使用情况下,我们在这里谈论,在Python简单的重新实现是一个更好的主意。

一方面,有〜80行代码,整个事情意味着它很容易弄清楚是怎么回事,如果需要不同的行为,你可以破解它变成一个新的脚本,在较短的时间比需要得到一个像堆栈溢出的地方回复。

见https://github.com/johnallsup/jda-misc-scripts/blob/master/yargs和https://github.com/johnallsup/jda-misc-scripts/blob/master/zargs.py 。

随着书面(并安装了Python 3)yargs可以键入:

find .|grep "FooBar"|yargs -l 203 cp --after ~/foo/bar

做复制203个文件在同一时间。 (这里的203只是一个占位符,当然,用一个陌生的号码像203清楚地表明,这个数字有没有其他的意义。)

如果你真的想要的东西更快,而不需要Python中,采取zargs和yargs为原型,并用C ++重写或C.



Answer 20:

您可能需要到grep Foobar的目录,如:

find . -name "file.ext"| grep "FooBar" | xargs -i cp -p "{}" .


Answer 21:

如果你使用bash,你可以转换标准输出由线组成的数组mapfile

find . | grep "FooBar" | (mapfile -t; cp "${MAPFILE[@]}" ~/foobar)

其优点是:

  • 它内置的,所以它的速度更快。
  • 在同一时间的所有文件名执行该命令,所以它的速度更快。
  • 您可以附加其他参数的文件名。 对于cp ,你还可以:

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

    但是,某些命令没有这样的功能。

缺点:

  • 如果有太多的文件名可能无法很好地扩展。 (极限?我不知道,但我曾与10 MB列表文件,其中包括没有问题10000 +文件名进行测试,在Debian下)

嗯......谁知道Bash是可在OS X?



文章来源: How can I use xargs to copy files that have spaces and quotes in their names?