【问题标题】:Use xargs to mv a directory from find results into another directory使用 xargs 将查找结果中的目录 mv 到另一个目录中
【发布时间】:2012-12-03 16:45:12
【问题描述】:

我有以下命令:

find . -type d -mtime 0 -exec mv {} /path/to/target-dir \;

这会将创建的目录移动到另一个目录。我怎样才能使用xargs 而不是exec 来做同样的事情。

【问题讨论】:

  • 为什么要使用xargs 而不是-exec

标签: shell find xargs mv


【解决方案1】:

使用BSD xargs(适用于OS X和FreeBSD),您可以使用为此而构建的-J

find . -name some_pattern -print0 | xargs -0 -J % mv % target_location

这会将. 中与some_pattern 匹配的任何内容移动到target_location

使用 GNU xargs(对于 Linux 和 Cygwin),请改用 -I

find . -name some_pattern -print0 | xargs -0 -I % mv % target_location

GNU xargs 已弃用的-i 选项暗示-I{},可以按如下方式使用:

find . -name some_pattern -print0 | xargs -0 -i mv {} target_location

请注意,BSD xargs 也有一个 -I 选项,但它还有其他作用。

【讨论】:

  • 在 Solaris 上我使用了:find . -name some_pattern | xargs -I % mv % target_location。谢谢
【解决方案2】:

如果你有 GNU mv(和 findxargs),你可以使用 -t 选项到 mv(和 -print0find-0 到 @ 987654330@):

find . -type d -mtime -0 -print0 | xargs -0 mv -t /path/to/target-dir

请注意,find 的现代版本(与 POSIX 2008 兼容)支持 + 代替 ;,并且在不使用 xargs 的情况下其行为与 xargs 大致相同:

find . -type d -mtime -0 -exec mv -t /path/to/target-dir {} +

这使得find 将方便数量的文件(目录)名称组合到程序的单个调用中。您无法控制xargs 提供的传递给mv 的参数数量,但您实际上很少需要它。这仍然取决于 GNU mv-t 选项。

【讨论】:

  • @jlliagre:你查过-t选项的含义了吗?后面是目标目录名称,这意味着最后一个参数毕竟不是目标,因此完全可以与xargs 一起使用。
  • 对不起,你是对的。我将-t 误读为xarg 参数。
  • 很棒的提示。一个建议 - 不要使用那种凌乱的 print0..-0 方法,而是使用 xargs -d'\n'
  • @Sridhar-Sarnobat:-print0-0 方法甚至适用于包含换行符的文件名;你的替代方案没有。诚然,很少有文件的名称中包含换行符,但以 null 结尾的符号的意义在于它无一例外地涵盖了所有个文件名。
  • 谢谢乔纳森。我没有意识到文件名可以有换行符。
【解决方案3】:
find ./ -maxdepth 1 -name "some-dir" -type d -print0 | xargs -0r mv -t x/

查找: 使用选项-print0,输出将以'\0'结尾;

xargs: 使用选项-0,它会将args 拆分为'\0' 但空格,-r 表示no-run-if-empty,因此如果find 没有得到任何输出,您将不会收到任何错误。 (-r 是 GNU 扩展。)

当我不确定目标文件是否存在时,我通常在脚本中使用它。

【讨论】:

    【解决方案4】:

    find 并不是一个很好的工具。我想您想将所有子目录移动到另一个目录中。 find 会输出类似

    ./a
    ./a/b
    ./a/b/c
    ./a/b/c/d
    

    ./a 首先移动后,您只会收到有关“没有这样的文件或目录”所有子目录的错误。

    您应该只使用 mv */ /another/place -- 通配符上的尾部斜杠将扩展限制为仅 dirs。

    【讨论】:

      【解决方案5】:

      如果您不使用 GNU mv,则可以使用该命令:

      find . -depth -type d -mtime 0 -exec bash -c 'declare -a array;j=1;for i; do array[$j]="$i"; j=$((j+1));done; mv "${array[*]}" /path/to/target-dir' arg0 {} +
      

      否则,这是一个不需要 xargs 的更简单的解决方案:

      find . -depth -type d -mtime 0 -exec mv -t /path/to/target-dir {} +
      

      请注意,我添加了 -depth 否则在同时处理目录及其子目录之一时会出现错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-13
        • 2013-06-27
        • 2013-11-21
        • 1970-01-01
        • 2020-02-20
        • 2014-07-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多