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
如果您有任何问题,请告诉我。
在 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
如果您有任何问题,请告诉我。