it-swarm.cn

如何用mv覆盖目标文件?

我想移到父目录的子目录中有大量文件和目录。目标目录中已经有一些文件和目录需要覆盖。仅存在于目标中的文件应保持不变。我可以强迫mv这样做吗?它(mv * ..)抱怨

mv: cannot move `xyz' to `../xyz': Directory not empty

我想念什么?

175
EricSchaefer

您必须使用命令cp -r * ..rm -rf *将它们复制到目标,然后删除源。

我认为您不能使用mv“合并”目录。

128
dogbane

rsync可能是一个更好的选择。就像rsync -a subdir/ ./

我的测试树采用filenamecontents格式:

./file1:root
./file2:root
./dir/file3:dir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

运行rsync

$ rsync -a -v subdir/ ./
sending incremental file list
./
file1
dir/
dir/file3

给出:

./file1:subdir
./file2:root
./dir/file3:subdir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

然后,要模拟mv,您可能要删除源目录:

$ rm -r subdir/

给予:

./file1:subdir
./file2:parent
./dir/file3:subdir
./dir/file4:dir

如果这是错误的,您能否提供类似的示例(例如,从此答案顶部附近使用我的测试树)并获得所需的结果?

77
Mikel

使用--remove-source-files参数复制后,rsync可以删除源。这应该是完成您想要的事情的便捷方法。

rsync man page

        --remove-source-files   sender removes synchronized files (non-dir)
52
Mike Chen

您可以使用cprm进行此操作,但无需复制大量数据(大概)是为了避免传输。 @ -mattdm在 他的评论 中暗示了这一点,在 另一个问题的答案 中对各种选项进行了更完整的讨论。

cp -rlf source destination
rm -r source

本质上,cp命令的-l选项创建到文件的硬链接,而不是将其数据复制到新文件。

24
palswim

这是一个脚本,用于将文件从/path/to/source/root下移动到/path/to/destination/root下的相应路径。

  • 如果源目录和目标目录中都存在目录,则将以递归方式移动和合并内容。
  • 如果源中存在文件或目录,但目标中不存在,则将其移动。
  • 目标中已存在的任何文件或目录都将被留下。 (特别是合并的目录留在了源代码中。这不容易解决。)

当心,未经测试的代码。

export dest='/path/to/destination/root'
cd /path/to/source/root
find . -type d \( -exec sh -c '[ -d "$dest/$0" ]' {} \; -o \
                  -exec sh -c 'mv "$0" "$dest/$0"' {} \; -Prune \) \
    -o -exec sh -c '
        if ! [ -e "$dest/$0" ]; then
          mv -f "$0" "$dest/$0";
        fi
' {} \;
9

这个线程已经存在多年了,但在Google上仍然排名第一,所以我想添加另一种方法。我通常的操作方式是:将subdir内容打包到tarball中,将tarball移至父目录,然后使用默认的--overwrite行为将其提取。这正是您想要的。之后,您可以删除您的子目录。

cd xyz
tar -cvzpf tmp.tar.gz *
mv tmp.tar.gz ../tmp.tar.gz
cd ..
tar -xvzpf tmp.tar.gz
rm -rf xyz
rm -f tmp.tar.gz
3
Simon Kraus

如果您有足够的存储空间,则可以通过以下方式进行:

mv -bfv directory_1/* directory_2/ # all duplicate source files/directories 
                                   # will have ~ appended to them
find -name "*~" -delete            # will recursively find and delete all files 
                                   # with ~ on the end

确保没有任何重要文件在文件末尾带有〜,但是如果有,您可以添加--suffix=whateveryouwant而不是默认值。

0
4D3H2