【问题标题】:Not working: find -print0 | xargs -0 bash -c "...."不工作:find -print0 | xargs -0 bash -c "...."
【发布时间】:2016-03-27 08:57:50
【问题描述】:

O/S = RHEL 7.2

如您所料,下面的前两行打印“dbg”,然后是 /home/mydir 下的所有文件。但如果我使用 -print0 和 xargs -0,如后两行所示,则第一个文件在目录中被跳过。我尝试将 echo 更改为 echo dbg "$0" $@" 只要子目录中有文件,它就可以工作。在一个空的子目录中,$0 返回“bash”。

# This works
dir=/home/mydir
find "$dir" -maxdepth 1 -type f -print | xargs  bash -c '/bin/echo dbg "$@"'  

# This skips the first file
dir=/home/mydir
find "$dir" -maxdepth 1 -type f -print0 | xargs -0 bash -c '/bin/echo dbg "$@"'

【问题讨论】:

  • 工作完全符合预期(Linux Mint 17.3,GNU bash,版本 4.3.11(1)-release (x86_64-pc-linux-gnu))。两行给出相同的输出。
  • 很高兴知道。我正在 RHEL 7.2 上进行测试。我已经编辑了问题以包括,以及对我所看到的实际行为的一些更正。
  • 你不需要xargsfind "$dir" -maxdepth 1 -type f -exec bash -c '/bin/echo dbg "$@"' _ {} \;。事实上,你甚至根本不需要bashfind "$dir" -maxdepth 1 -type f -exec /bin/echo dbg {} \;
  • 两者都好。我应该指出这是一个旨在隔离问题的简化示例。在现实生活中,我正在调用用户定义的 bash 函数——这就是我需要调用 bash 的原因。而且我不想使用find -exec,因为我将调用该函数数十万次。鉴于我的函数中的实用程序的性质(例如 setfacl),使用 xargs 可以为我节省大量时间。

标签: bash find xargs


【解决方案1】:

当您使用bash -c 'command' arg0 arg1 arg2 … 时,表示为arg0 的参数被视为$0,即脚本的名称(因此不是"$@" 的一部分)。

您可以通过以下方式进行演示:

$ bash -c 'echo dbg "$@"' a b c
dbg b c
$ bash -c 'echo dbg "$@"' name a b c
dbg a b c
$ bash -c 'echo dbg [$0] "$@"' name a b c
dbg [name] a b c
$

用途:

find "$dir" -maxdepth 1 -type f -print0 | xargs -0 bash -c '/bin/echo dbg "$@"' name

【讨论】:

  • 谢谢;我正在寻找这样的东西;我终于明白了我在其他地方看到的那个占位符的用法。我仍然对使用 -print 和 -print0 之间的区别感到困惑,但是一旦一切正常,我将重新审视它。如果我学到任何有趣的东西,我会在这里发布。
  • 要查看-print0-0 的好处,您需要有包含空格或类似名称的文件名,以及正确检测参数边界的方法("$@" 是其中的一部分答案,但echo 可能不是;也许使用printf "[%s]\n" 而不是echo)。包含换行符、制表符和其他奇数字符的文件名也是如此。
  • 感谢您的解释——但我想我并不清楚。我指的是原始问题陈述,其中 -print 和 -print0 的行为不同。要么我没能理解一些基本的东西,要么我在测试中犯了一个根本性的错误。 (在我回去重新测试所有东西之前,我不能忽视后者。由于我不明白发生了什么,我不能发誓我在测试中没有做任何愚蠢的事情。)
  • 默认情况下,xargs 会运行一次命令,即使没有文件也是如此。使用 GNU xargs,您可以使用 -r(或 --no-run-if-empty)抑制它。如果因为没有文件而没有指定arg0,那么使用的名称毕竟是bash。单个文件将用作arg0 等。
  • 谢谢,乔纳森!我从没想过要寻找-r之类的东西。不过,这很有意义,并清理了我代码的其他方面。非常感谢。
猜你喜欢
  • 2014-10-25
  • 2013-04-05
  • 2010-11-02
  • 2010-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多