我想递归地将文件从一个文件夹(图片)移动到另一个文件夹(图片新)。
“图片”文件夹有很多子文件夹,因此我在跟进此处的帖子后使用了此命令。
Pictures 和 Picturesnew 都位于同一目录中。我只是想删除所有子文件夹并合并数据。
我从这些文件夹所在的目录运行以下命令。
find ./Pictures -type f -name "*.jpg" -print0 |
xargs -0 -Imysongs mv -i mysongs ./Picturesnew
现在看起来应该出现的Picturesnew文件夹根本没有出现,因此我很困惑我的20000个JPG文件去了哪里。
答案1
你真的想要
mkdir Picturesnew
find Pictures -type f -iname "*.jpg" -exec mv -i {} + Picturesnew/
mv 不创建目录。
mv 的 -i 选项导致它在这样的管道中运行时无法工作。 (不过,从好的方面来说,它希望告诉 mv 不要践踏第一个重命名为 Picturesnew 的文件,而不是原来的文件。)
在我的解决方案中,我告诉 find 如果有用的话,在每个执行的 mv 实例中移动多个文件,以最大程度地减少出现错误的可能性,例如保留目标目录名称的尾部 / 以及没有使目标目录实际重命名文件,而不是生成所需的错误。它还具有允许 mv 实际上提示确认覆盖文件而不是简单地将下一个文件名视为“否”的优点。
答案2
我不知道为什么覆盖时没有确认,由于-i
的参数,应该存在确认mv
。但假设你没有使用它,并且考虑到Picturesnew
操作后有一个 jpg 文件,正如你在问题下的评论中所述,那么 - 你覆盖了同一个文件 20000 次。
xargs -0 -Imysongs mv -i mysongs ./Picturesnew
这意味着对于每个参数都会执行此命令:
mv -i argument ./Picutesnew
由于没有目录,./Picturesnew
该命令mv
认为您的意思是它应该将文件移动到此处并重命名为./Picturesnew
.它这样做了 20000 次。
管道执行完毕后,应该只剩./Picturesnew
下一个文件。最后一个被移动的。以前的都没有了。
因此,这种形式更安全:
mv -i argument ./Picturesnew/
那是因为/
最后消除了对Picturesnew
应该是什么的混乱。
至于-i
,您不会将其放入此管道中,因为它不起作用。它需要确认。
答案3
我认为您可以通过以下命令实现您的目标:
find Pictures -type f -print0 | xargs -0 mv -t Picturesnew
其中Pictures
是源目录,Picturesnew
是目标目录。
两者mv
(和cp
)都具有mv -t directory source...
非常适合与 一起使用的格式xargs
。
但是此方法会将具有重复名称的文件保留在其原始位置(也许这还不错,因为您可以稍后查看它们并复制到目标),因为mv -t
使用输入重定向时将无法交互工作。这是因为xargs
已经从重定向的标准输入(这是 的输出find
)读取值,并且mv
由 运行的xargs
也尝试从相同的标准输入读取答案。因此,您不能以交互方式将 mv 与管道一起使用。
也许工作可以通过一些巧妙的输入句柄重新分配来解决,但让我们尝试更简单的方法:摆脱输出重定向。此外,我们不能-print0
在命令替换中使用,因为它不允许 0 字节。我们需要使用for
,迭代文件名使用换行符作为输入字段分隔符:
TMP=$IFS;
IFS=$'\n';
for i in $(find Pictures -type f); do
mv -it ../Picturesnew $i;
done;
IFS=$TMP
(您可以将其复制为一行)。
在这种情况下,mv 不仅会询问您每个重复项,还会等待答案。
答案4
find Pictures -type f -iname "*.jpg" -print0 | xargs -0 -I {} mv -n "{}" Picturesnew/
这将是一个语法上更正确的解决方案,因此恢复您的备份并尝试一下。