BASH - 使用 mv 时合并目录

BASH - 使用 mv 时合并目录

我刚开始使用 BASH,所以我可以将一个目录的所有内容移动到另一个目录。但问题是,我期望它合并目录。我正在使用 cron 作业来运行此脚本。

#!/bin/bash

shopt -s dotglob nullglob
mv mv_schedule/* public_html/

来源:(/mv_schedule/包含文件夹/文件)

/files/
4.html
5.html
/assets/
sitemap.xml

目标:(/public_html/先前的文件夹已经存在)

/files/
1.html
2.html
3.html
/assets/
sitemap.xml

所以我想要的是,将这些目录中的所有新文件/mv_schedule/与中的文件合并/public_html/,并将其中已经存在的文件替换为来自的文件/mv_schedule/

当我使用当前脚本尝试此操作时,它当前通过电子邮件返回此错误:

mv: cannot move `mv_schedule/assets' to `public_html/assets': Directory not empty

我怎样才能解决这个问题?

答案1

错误消息告诉您,它无法 mv asset 目录,因为该目录中有文件。mv 目录意味着进行复制,然后删除它,并且无法删除它,因为它仍包含一些文件。这意味着您还应该 mv asset 内的文件,甚至应该 mv asset 内的子目录和子目录中的文件(如果存在)。但是发出的 mv 命令只能复制(和删除)mv_schedule 目录中的内容,而不能复制 mv_schedule 内子目录(如 asset)中的内容。

您需要的是一个命令,该命令会将目录树向下移动到最后一个叶子节点并进行复制,类似于 rm、chmod、chown 中的 -r 或 -R 选项。但是,mv 没有这样的选项,因此您必须使用 find 命令,该命令会从您指定的根节点向下移动到整个目录树,然后执行您指定的操作。对于您的情况,合适的命令是:

SOURCE_DIR=$1
TARGET_DIR=$2
find $SOURCE_DIR -name '*' -type f -exec mv -f {} $TARGET_DIR \;

这会将所有文件堆积到单个目标目录中。它假定您将源目录和目标目录作为输入行参数传递给 bash 脚本。-f 选项可防止在覆盖时要求确认,您可以将其更改为 -n(不覆盖)或 -i(覆盖前询问)。

如果您希望保留目录结构,请记住 cp 命令可以降低目录树,因此您可以使用该命令,然后使用 rm,因为该命令也可以降低目录树。一组可能的命令是:

SOURCE_DIR=$1
TARGET_DIR=$2
cp -a $SOURCE_DIR $TARGET_DIR
rm -rf $SOURCE_DIR

注意 cp 中的 -a 选项:它保留时间戳和所有权。如果您不关心这些事情,您可以改用 -R。

答案2

有一个更通用的这个问题的讨论在 Unix 部分。

-l您可以使用cp命令,创建硬链接同一文件系统上的文件,而不是完整数据副本。以下命令将文件夹复制到已包含名为 的目录source/folder的父文件夹 ( ) 。destinationfolder

cp -rl source/folder destination
rm -r source/folder

笔记:

  • 根据您的需要,您可能还想使用-P--no-dereference- 不取消引用符号链接)或-a--archive- 保留所有元数据,还包括选项)。-P
  • 虽然涉及两个“I/O”步骤,但这些步骤都是相对简单的元数据操作,不涉及任何“数据”传输。因此,此方法比 cp(无-l)或基于 rsync 的解决方案快几个数量级。
  • 这确实不是如果源文件夹和目标文件夹位于不同的文件系统上,则可以工作

相关内容