我正在尝试编写一个脚本来将今天创建的一组目录复制到另一个目录。
我目前正在使用:
find /test/downloads/ -mindepth 1 -maxdepth 1 -type d -mtime -1 -printf '%f\n' | xargs -I '{}' cp -R '{}' /test/uploads/
但这给了我一个错误:
cp: cannot stat 'foo': No such file or directory
我缺少什么?
答案1
-printf '%f\n'
是一个 GNU 扩展,它打印当前文件路径的尾部,后跟换行符。如果文件路径是/test/downloads/foo
,则打印foo\n
。
xargs
获取该输出。这里foo
不包含任何由xargs
with特殊处理的字符-I{}
(引用字符、换行符(唯一的分隔符-I
)和前导空格、EOF 字符)。
So在传递给 的参数中{}
被替换为。因此最终会以, , ,作为参数进行调用。foo
cp
cp
cp
-R
foo
/test/uploads/
因此将在当前工作目录中cp
查找,而不是在.foo
/test/downloads
如果该文件已被调用/test/downloads/-t..
,则该命令将是
cp -R -t.. /test/uploads/
它告诉cp
复制/test/uploads/
到当前工作目录的父目录。
如果文件名是/test/downloads/ 'blah'<newline>"blah"
,cp
就会被调用两次cp -R blah /test/uploads/
。
所以你有两个问题:
- 使用
%f
,您可以将前导目录组件剥离到文件中 - 您正在使用的
xargs
不能在输出上可靠地使用find
(除了使用非标准-r
和-0
处理 NUL 分隔记录的选项)。
还可以补充一点,cp
尽管cp
您能够一次复制多个文件,但您正在调用每个目录。
在这里,标准地应该是:
find /test/downloads/. ! -name . -prune -type d -mtime -1 -exec sh -c '
exec cp -R "$@" /test/uploads/' sh {} +
通过这些实用程序的 GNU 实现(在 Debian 系统中默认找到)可以简化为:
find /test/downloads/ -mindepth 1 -maxdepth 1 -type d -mtime -1 \
-exec cp -Rt /test/uploads/ {} +
答案2
您可能有一个名为“ ”的文件foo bar
。
更好的方法是将从你-printf ...
到最后替换为:
-print0 | xargs -0 -r cp -t /Test/Uploads
读man find xargs cp
。