![如何将 find 命令与 mv 命令集成?](https://linux22.com/image/194644/%E5%A6%82%E4%BD%95%E5%B0%86%20find%20%E5%91%BD%E4%BB%A4%E4%B8%8E%20mv%20%E5%91%BD%E4%BB%A4%E9%9B%86%E6%88%90%EF%BC%9F.png)
我试图将名称以大写字母开头的所有文件从当前目录移动到名为u
under 的目录~/tmp
。
我尝试了这个命令:find . -type f -name "*[[upper]]*" -exec mv -t ~/tmp/u
但它不起作用。
答案1
你们非常接近。
您需要在
[[:upper:]]
标记中使用冒号。"*[[:upper:]]*"
会找到每一个名字包含一个大写字母。仅获取其名称的文件开始对于大写字母,请使用"[[:upper:]]*"
(省略第一个*
)。如果你说只是
find . -name '[[:upper:]]*'
它会列表名称以大写字母开头的所有文件。但是,当您使用 时
-exec
,您必须告诉find
在命令中包含文件名,使用{}
.(而且你应该总是
find
在尝试告诉它运行命令之前,请以仅打印模式调试命令,尤其是修改文件系统的命令。使用 是一种常见的调试技术。)-exec echo mv …
但是,当您使用 时
-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
要么重命名a
为b
(搬去) 或者b/a
(搬进)取决于是否b
是目录。通过添加尾随/
,我们确保它是后者,或者至少如果b
不是目录,则会报告错误而不是重命名a
为b
(执行搬去)。在上面的代码中,这是针对只找到一个文件的find
情况。 (移动多个文件)始终是find
mv a b c
搬进操作(需要c
是一个目录),如搬去在这种情况下没有意义。
答案3
find . -type f -name "[A-Z]*" -exec mv {} <destination directory> \;