bash xargs -0 后如何执行多个命令?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7472933/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 21:03:19  来源:igfitidea点击:

How to execute multiple commands after xargs -0?

bashfindxargs

提问by Richard Chen

find . -name "filename including space" -print0 | xargs -0 ls -aldF > log.txt
find . -name "filename including space" -print0 | xargs -0 rm -rdf

Is it possible to combine these two commands into one so that only 1 find will be done instead of 2?

是否可以将这两个命令合二为一,以便只执行 1 个查找而不是 2 个?

I know for xargs -I there may be ways to do it, which may lead to errors when proceeding filenames including spaces. Any guidance is much appreciated.

我知道 xargs -我可能有办法做到这一点,这可能会导致在处理包含空格的文件名时出错。非常感谢任何指导。

采纳答案by Jonathan M

If you're just wanting to avoid doing the findmultiple times, you could do a teeright after the find, saving the findoutput to a file, then executing the lines as:

如果您只是想避免find多次执行,则可以tee在 之后立即执行find,将find输出保存到文件,然后执行以下行:

find . -name "filename including space" -print0 | tee my_teed_file | xargs -0 ls -aldF > log.txt
cat my_teed_file | xargs -0 rm -rdf 

Another way to accomplish this same thing (if indeed it's what you're wanting to accomplish), is to store the output of the findin a variable (supposing it's not TB of data):

完成同样事情的另一种方法(如果确实是您想要完成的)是将 的输出存储find在变量中(假设它不是 TB 数据):

founddata=`find . -name "filename including space" -print0`
echo "$founddata" | xargs -0 ls -aldF > log.txt
echo "$founddata" | xargs -0 rm -rdf

回答by glenn Hymanman

find . -name "filename including space" -print0 | 
  xargs -0 -I '{}' sh -c 'ls -aldF {} >> log.txt; rm -rdf {}'

回答by Richard Chen

I believe all these answers by now have given out the right ways to solute this problem. And I tried the 2 solutions of Jonathan and the way of Glenn, all of which worked great on my Mac OS X. The method of mouviciel did not work on my OS maybe due to some configuration reasons. And I think it's similar to Jonathan's second method (I may be wrong).

我相信现在所有这些答案都给出了解决这个问题的正确方法。我尝试了 Jonathan 的 2 个解决方案和 Glenn 的方式,所有这些都在我的 Mac OS X 上运行良好。 mouviciel 的方法在我的操作系统上不起作用可能是由于某些配置原因。而且我认为它类似于乔纳森的第二种方法(我可能错了)。

As mentioned in the comments to Glenn's method, a little tweak is needed. So here is the command I tried which worked perfectly FYI:

正如对 Glenn 方法的评论中所述,需要稍作调整。所以这是我尝试过的命令,它完美地工作,仅供参考:

find . -name "filename including space" -print0 | 
xargs -0 -I '{}' sh -c 'ls -aldF {} | tee -a log.txt ; rm -rdf {}'

Or better as suggested by Glenn:

或者按照格伦的建议更好:

find . -name "filename including space" -print0 | 
xargs -0 -I '{}' sh -c 'ls -aldF {} >> log.txt ; rm -rdf {}'

回答by Ole Tange

As long as you do not have newline in your filenames, you do not need -print0 for GNU Parallel:

只要您的文件名中没有换行符,就不需要 -print0 用于 GNU Parallel:

find . -name "My brother's 12\" records" | parallel ls {}\; rm -rdf {} >log.txt

Watch the intro video to learn more: http://www.youtube.com/watch?v=OpaiGYxkSuQ

观看介绍视频以了解更多信息:http: //www.youtube.com/watch?v=OpaiGYxkSuQ

回答by Sridhar Sarnobat

Just a variation of the xargsapproach without that horrible -print0and xargs -0, this is how I would do it:

就在一个变化xargs的方法没有那样可怕-print0xargs -0,这是我会怎么做:

ls -1 *.txt  | xargs --delimiter "\n" --max-args 1 --replace={} sh -c 'cat {}; echo "\n"'

Footnotes:

脚注:

  • Yes I know newlines can appear in filenames but who in their right minds would do that
  • There are short options for xargsbut for the reader's understanding I've used the long ones.
  • I would use ls -1when I want non-recursive behavior rather than find -maxdepth 1 -iname "*.txt"which is a bit more verbose.
  • 是的,我知道换行符可以出现在文件名中,但谁会这样做
  • 有一些简短的选项,xargs但为了读者的理解,我使用了较长的选项。
  • ls -1当我想要非递归行为而不是find -maxdepth 1 -iname "*.txt"更冗长时,我会使用。

回答by Phil Freed

I'm late to the party, but there is one more solution that wasn't covered here: user-defined functions. Putting multiple instructions on one line is unwieldy, and can be hard to read/maintain. The for loop above avoids that, but there is the possibility of exceeding the command line length.

我迟到了,但这里没有涵盖另一种解决方案:用户定义的函数。将多个指令放在一行上很笨拙,并且可能难以阅读/维护。上面的 for 循环避免了这种情况,但有可能超过命令行长度。

Here's another way (untested).

这是另一种方式(未经测试)。

function processFiles {
  ls -aldF "$@"
  rm -rdf "$@"
}
export -f processFiles

find . -name "filename including space"` -print0 \
  | xargs -0 bash -c processFiles dummyArg > log.txt

This is pretty straightforward except for the "dummyArg" which gave me plenty of grief. When running bash in this way, the arguments are read into

这很简单,除了“dummyArg”让我很伤心。以这种方式运行 bash 时,参数被读入

"
"" "" ""    ....
" "" "" ....

instead of the expected

而不是预期的

IFS=$'\n'
for F in `find . -name "filename including space"`
do
    ls -aldF $F > log.txt
    rm -rdf $F
done

Since processFiles{} is expecting the first argument to be "$1", we have to insert a dummy value into "$0".

由于 processFiles{} 期望第一个参数是“ $1”,我们必须在“ $0”中插入一个虚拟值。

Footnontes:

脚注:

  1. I am using some elements of bash syntax (e.g. "export -f"), but I believe this will adapt to other shells.
  2. The first time I tried this, I didn't add a dummy argument. Instead I added "$0" to the argument lines inside my function ( e.g. ls -aldf "$0" "$@"). Bad idea. Aside from stylistic issues, it breaks when the "find" command returns nothing. In that case, $0 is set to "bash", Using the dummy argument instead avoids all of this.
  1. 我正在使用 bash 语法的一些元素(例如“ export -f”),但我相信这将适用于其他 shell。
  2. 我第一次尝试这个时,我没有添加一个虚拟参数。相反,我在函数内的参数行中添加了“ $0”(例如ls -aldf "$0" "$@")。馊主意。除了文体问题,当“ find”命令不返回任何内容时,它会中断。在这种情况下,$0 设置为“bash”,而使用 dummy 参数可以避免所有这些。

回答by ericbn

You can execute multiple commands after findusing forinstead of xargs:

find使用for代替后可以执行多个命令xargs

find . -name "filename including space" -print0 \
| xargs -0 -I FOUND echo "$(ls -aldF FOUND > log.txt ; rm -rdf FOUND)"

The IFSdefines the Internal Field Separator, which defaults to <space><tab><newline>. If your filenames may contain spaces, it is better to redefine it as above.

IFS定义了内部字段分隔符,缺省值为<空间> <标签> <换行符>。如果您的文件名可能包含空格,最好像上面那样重新定义它。

回答by mouviciel

Another solution:

另一种解决方案:

##代码##