【问题标题】:How to pipe the results of 'find' to mv in Linux如何在 Linux 中将“find”的结果通过管道传输到 mv
【发布时间】:2014-04-18 18:27:36
【问题描述】:

如何通过管道将“查找”的结果(在 Linux 中)移动到不同的目录?这是我目前所拥有的。

find ./ -name '*article*' | mv ../backup

但它还不正确(我收到一个错误缺少文件参数,因为我没有指定文件,因为我试图从管道中获取它)

【问题讨论】:

标签: linux unix


【解决方案1】:
find ./ -name '*article*' -exec mv {}  ../backup  \;

find ./ -name '*article*' | xargs -I '{}' mv {} ../backup

【讨论】:

  • 当我运行你的第二个命令时,它说 xargs: invalid option -- I. 这里有什么问题?我看到它是手册页上的一个有效选项。
  • @user1015214 - 此页面上的 4 个命令都不适合您吗?
  • 没有。如果有帮助,我在 Windows 机器上的 git Bash 中。好像是在运行 linux 命令,但我猜它没有完整的库?
  • @user1015214 - 可能 git bash 是有限的。由于您在 Windows 机器上,我建议在Powershell 中使用Move-Item Cmdlet。你可以做Move-Item *article* \full\path\to\backup
【解决方案2】:

xargs 常用于此目的,而 Linux 上的 mv 有一个 -t 选项来促进此目的。

find ./ -name '*article*' | xargs mv -t ../backup

如果你的 find 支持 -exec ... \+ 你也可以这样做

find ./ -name '*article*' -exec mv -t ../backup {}  \+

-t 选项是一个 GNU 扩展,因此它不能移植到没有 GNU coreutils 的系统上(尽管我见过的每个适当的 Linux 都有这个,可能除了 Busybox)。对于完整的 POSIX 可移植性,当然可以推出您自己的替代品,可能类似于

find ./ -name '*article*' -exec sh -c 'mv "$@" "$0"' ../backup {} \+

我们无耻地滥用sh -c 'commands' 之后的第一个参数作为$0 中的“脚本名称”参数结束的便利事实,因此我们甚至不需要shift 它。

【讨论】:

  • 当我尝试你的第一个建议时,它说'invalid option -- t'。当我尝试您的第二个时,它说找不到 -exec 命令,所以我猜它不支持。
  • 听起来你毕竟不在 Linux 上,因为这些工具的 GNU 版本已经支持了很长时间。我找不到(原文如此)不支持 some 形式的-execfind -- 也许您输入了错误的命令?
【解决方案3】:

我发现在一个文件夹中包含数千个文件非常有用:

ls -U | head -10000 | egrep '\.png$' | xargs -I '{}' mv {} ./png

将前 10000 个文件中的所有 png 移动到子文件夹 png

【讨论】:

  • 正则表达式没有egrep(更现代的又名grep -E)语法,您可以分解出headgrep -m 10000 '\.png$',更一般地,您应该avoid ls in scripts
  • 也许printf '%s\0' *.png | xargs -r0 mv -t png/ 避免了ls 的各种问题,而printf '%s\0' *.png | grep -z -m 10000 ^ | xargs -r0 mv -t png/ 巧合地使用grep -z -m items 作为head 的替代品以空结尾的输入。我之前发布的链接更详细地解释了这些事情。我对改进主张ls的答案意见不一;但请随意更新您认为合适的内容,并包括来自这些 cmets 的任何内容。顺便说一句,xargs -0 仅适用于 GNU(应该可以在 Linux 上运行,但不能正确移植)。
【解决方案4】:

xargs 是您的好友(当您有多项操作要执行时)!

并且按照我展示的方式使用它也会给你很大的控制权。

find ./ -name '*article*' | xargs -n1 sh -c "mv {}  <path/to/target/directory>"

说明:

  1. -n1

每个操作需要考虑的行数

  1. sh -c

执行的shell命令根据之前的条件给它行

  1. "mv {} /target/path"

移动命令将采用两个参数-

1) 操作 1 中的行,即 {},值自动替换

2) 指定的移动命令的目标路径

注意:“双引号”被指定为允许从 xargs 接收参数的 shell 命令使用任意数量的空格或参数

【讨论】:

  • 为什么需要-n1,那么sh -c 包装器的目的是什么?仅此。与其他较旧的类似答案相比,它带来了缺点。
  • 感谢您的反馈。我使用这种语法已经有一段时间了。你能告诉我缺点吗?它只会帮助我更好地了解情况
  • 如果你只循环一个参数,sh -c 是没有用的。另一方面,-n 1 基本上也使xargs 无用;如果您一次只移动一个文件,只需运行find -exec。但是,一次只处理一个文件是非常浪费的。您通常应该尽量减少子进程的数量。之前的答案实施了各种优化来做到这一点,其中一些比其他的更积极和稳健。
【解决方案5】:
mv $(find . -name '*article*') ../backup

【讨论】:

  • 此命令不正确。它说missing file operand。 (我在 ../backup 之前使用了 -t 来定义目标目录)
  • 它对我有用。您的备份目录应该放回您的搜索目录。
  • 这很容易产生无效的文件名。生成源文件名列表的命令替换本质上是有问题的。如果您在微不足道的情况下对其进行测试,它看起来会起作用,但如果您的文件名中包含空格或 shell 元字符,它会严重损坏。 mywiki.wooledge.org/BashPitfalls 上的几个项目是此常见问题解答的变体。
【解决方案6】:
  • 如何在 Linux 中将 'find' 的结果通过管道传输到 mv
  • find + mv 命令

找到 . -type f -newermt "2019-01-01" ! -newermt "2019-05-01" -exec mv {} 路径 \;

查找路径 -type f -newermt "2019-01-01" ! -newermt "2019-05-01" -exec mv {} 路径 \;

找到 /Directory/filebox/ -type f -newermt "2019-01-01" ! -newermt "2019-05-01" -exec mv {} ../filemove/ \;

【讨论】:

    猜你喜欢
    • 2014-12-01
    • 2014-02-03
    • 1970-01-01
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    • 1970-01-01
    • 2017-03-22
    • 2011-06-28
    相关资源
    最近更新 更多