如何将 find 命令与 mv 命令集成?

如何将 find 命令与 mv 命令集成?

我试图将名称以大写字母开头的所有文件从当前目录移动到名为uunder 的目录~/tmp

我尝试了这个命令:find . -type f -name "*[[upper]]*" -exec mv -t ~/tmp/u
但它不起作用。

答案1

你们非常接近。

  1. 您需要在[[:upper:]]标记中使用冒号。

  2. "*[[:upper:]]*"会找到每一个名字包含一个大写字母。仅获取其名称的文件开始对于大写字母,请使用"[[:upper:]]*"(省略第一个 *)。

  3. 如果你说只是

    find . -name '[[:upper:]]*'
    

    它会列表名称以大写字母开头的所有文件。但是,当您使用 时 -exec,您必须告诉find在命令中包含文件名,使用 {}.

    (而且你应该总是find在尝试告诉它运行命令之前,请以仅打印模式调试命令,尤其是修改文件系统的命令。使用 是一种常见的调试技术。)-exec echo mv …

  4. 但是,当您使用 时-exec,您必须以 ';' (或等效的 \;) 或 结束命令+。 (参见手册页, 或者Stéphane Chazelas 对这个问题的回答,为了区别。)由于您正在使用mv -t,因此您可以使用 +

所以你的最终命令是

find . -name '[[:upper:]]*' -exec mv -t ~/tmp/u {} +

答案2

GNU 实现的语法mv是:

find . -type f -name '[[:upper:]]*' -exec mv -t ~/tmp/u {} +

或者标准地:

find . -type f -name '[[:upper:]]*' -exec sh -c '
   exec mv "$@" ~/tmp/u/' sh {} +

这是为了匹配文件名的模式开始对于大写字母,您希望它匹配大写字母(方括号表达式[:upper:]内的 POSIX 字符类[...]),后跟任意数量的字符 ( *)。

你必须说出终点find在哪里-exec some command with its args。那是:

  • 一个;参数(在 shell 命令行中,您必须用引号引起来,例如';', \;, ";"... 这;也是所有 shell 中的特殊字符),它告诉find每个文件执行一次命令(在这种情况下,{}在命令行参数替换为文件的路径)。
  • 或参数的顺序{} +。只能有一个{},并且必须在 之前+。在这种情况下,一次针对多个文件调用该命令,并{}替换为文件列表。

所以find最终运行:

  • mv -t /home/you/tmp/u ./File1 ./File2 ./dir/File3...在第一种情况下,where-t允许所有源文件位于末尾。
  • sh -c 'mv "$@" ~/tmp/u/' sh ./File1 ./File2 ./dir/File3...POSIXly。如果没有-t,我们需要调用sh来重新排序参数,以便~/tmp/u/可以放在最后。在这里,sh最终运行:(mv ./File1 ./File2 ./dir/File3... /home/you/tmp/u/在同一进程中,因为exec;某些sh实现已经进行了优化,而不需要显式的exec)。

尾随/mv ... ~/tmp/u/为了确保mv输入搬进模式。mv a b要么重命名ab(搬去) 或者b/a搬进)取决于是否b是目录。通过添加尾随/,我们确保它是后者,或者至少如果b不是目录,则会报告错误而不是重命名ab(执行搬去)。在上面的代码中,这是针对只找到一个文件的find情况。 (移动多个文件)始终是findmv a b c搬进操作(需要c是一个目录),如搬去在这种情况下没有意义。

答案3

find . -type f -name "[A-Z]*" -exec mv  {} <destination directory> \;

相关内容