Linux 如果文件存在则移动文件而不替换

Linux move files without replacing if files exists

在 Linux 中,如果特定文件已存在于目标中,我如何移动文件而不替换?

我尝试了以下命令:

mv --backup=t <source> <dest>

文件没有被替换,但问题是扩展名被更改了,因为它在文件名后面加上了“~”。

有没有其他方法可以保留扩展名,但移动时只会更改文件名?

例如 test~1.txt 而不是 test.txt~1

扩展名被替换后,您将无法通过双击查看文件。

如果你想在 shell 中实现它,而不需要原子性(所以如果两个 shell 进程同时是 运行 相同的代码,你可能会遇到麻烦),您可以(使用 shell 的内置 test(1) 功能)

[ -f destfile.txt ] || mv srcfile.txt destfile.txt

如果你需要原子性(当两个进程同时运行时有效的东西 运行 它),事情是相当困难的,你需要在 C 中调用一些系统调用。查看 renameat2(2)

也许您应该考虑使用一些版本控制系统,例如 git ?

mv 有一个选项:

-S, --suffix=SUFFIX
          override the usual backup suffix

你可能会用到;但是 afaik mv 没有更改部分文件名而不是扩展名的功能。如果你只是想用文本编辑器打开备份文件,你可以考虑这样的东西:

mv --suffix=.backup.txt <source> <dest>

这是如何工作的:假设你有

-rw-r--r-- 1 chris users    2 Jan 25 11:43 test2.txt                                                                                                                                                                                                                           
-rw-r--r-- 1 chris users    0 Jan 25 11:42 test.txt

然后在命令 mv --suffix=.backup.txt test.txt test2.txt 之后你会得到:

-rw-r--r-- 1 chris users    0 Jan 25 11:42 test2.txt                                                                                                                                                                                                                           
-rw-r--r-- 1 chris users    2 Jan 25 11:43 test2.txt.backup.txt

如果移动具有相同文件名的文件,猜测 mv 命令非常有限。

下面是可用于移动的bash脚本,如果存在具有相同文件名的文件,它将在文件名后附加一个数字,并且扩展名也会被保留以便于查看。

我修改了可在此处找到的脚本: https://superuser.com/a/313924

#!/bin/bash
source=
dest=

file=$(basename $source)
basename=${file%.*}
ext=${file##*.}

if [[ ! -e "$dest/$basename.$ext" ]]; then
      mv "$source" "$dest"
else
      num=1
      while [[ -e "$dest/$basename$num.$ext" ]]; do
            (( num++ ))
      done
      mv "$source" "$dest/$basename$num.$ext" 
fi 

@aandroidtest:如果您能够依赖 Bash shell 脚本和源目录(文件当前所在的位置)和目标目录(您希望它们移动的位置) to) 是相同的文件系统,我建议你试试我写的脚本。您可以在 https://github.com/jmmitchell/movestough

找到它

简而言之,该脚本允许您将文件从源目录移动到目标目录,同时考虑到新文件、重复(相同文件名、相同内容)文件、文件冲突(相同文件名、不同内容) ),以及复制所需的子目录结构。此外,该脚本以三种形式处理文件冲突重命名。例如,如果 /some/path/somefile.name.ext 被发现是一个冲突文件。它将被移动到目标目录,其名称类似于以下名称之一,具体取决于所选择的消除冲突的样式(通过 -u=--unique-style= 标志):

  • 默认样式:/some/path/somefile.name.ext-<此处为唯一字符串>
  • 样式 1:/some/path/somefile.name.< 此处为唯一字符串 >.ext
  • 样式 2:/some/path/somefile.<此处为唯一字符串>.name.ext

如果您有任何问题,请告诉我。