我正在将文件移动到不同的文件夹,并且如果已存在同名文件(旧文件应保持不变),则希望向新移动的文件添加某种索引。例如,如果file.pdf
存在,我更喜欢类似file1.pdf
或file_1.pdf
的下一个同名文件。
这里我找到了相反想法的变体 - 但我不想进行“备份”。
是否mv
有一些针对该场景的开箱即用参数?我使用 Ubuntu Linux。
答案1
正如您链接的问题的答案已经指出的那样,mv
可以为文件添加后缀,否则这些文件会被您移动的文件覆盖,并使用数字为它们提供唯一的文件名:
mv --backup=t <source_file> <dest_file>
该命令的工作原理是将下一个未使用的数字后缀附加到目标目录中第一个文件中。您正在移动的文件将保留其原始名称。
但是,这会附加诸如 之类的后缀.~1~
,这似乎不是您想要的:
$ ls
file.pdf
file.pdf.~1~
file.pdf.~2~
您可以在第二步中重命名这些文件,以file_1.pdf
代替的格式获取名称file.pdf.~1~
,例如:
rename 's/((?:\..+)?)\.~(\d+)~$/_$2$1/' *.~*~
这将获取所有以不需要的备份后缀结尾的文件(通过与 shell glob 匹配*.~*~
),并让该rename
工具尝试匹配((?:\..+)?)\.~(\d+)~$
文件名上的正则表达式。如果匹配,它将捕获类似后缀的索引.~1~
作为第二组 ( $2
),并且可选地,如果文件名在该后缀之前有扩展名,例如.pdf
,则将由第一组 ( $1
) 捕获。然后,它将完整匹配的文件名部分替换为_$2$1
,并插入捕获的值而不是占位符。
基本上它会将eg重命名file.pdf.~1~
为file_1.pdf
和something.~42~
to something_42
,但它无法检测文件是否有多个扩展名,因此egarchive.tar.gz.~5~
会变成archive.tar_5.gz
答案2
我遇到的问题是 BASH 脚本在操作期间遇到/覆盖同名文件mv
。
解决mv --backup=t <src> <dest>
方案在这里,以及https://serverfault.com/questions/267255/mv-rename-if-exists效果很好。不过我也想保留文件扩展名。
这是一个解决方案。
[victoria@victoria out]$ ls -l
total 20
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 apple1.txt
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 apple2.txt
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 apple3.txt
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 apple4.txt
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 apple5.txt
[victoria@victoria out]$ for f in *; do mv -f --backup=t "$f" banana.txt; done
[victoria@victoria out]$ ls -l
total 20
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 banana.txt
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 banana.txt.~1~
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 banana.txt.~2~
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 banana.txt.~3~
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 banana.txt.~4~
[victoria@victoria out]$ for f in *; do mv 2>/dev/null -v "$f" "`echo $f | sed -r 's/(.*)\.(.*)\.~([0-9]{1,})~$/\1_\3.\2/'`"; done
renamed 'banana.txt.~1~' -> 'banana_1.txt'
renamed 'banana.txt.~2~' -> 'banana_2.txt'
renamed 'banana.txt.~3~' -> 'banana_3.txt'
renamed 'banana.txt.~4~' -> 'banana_4.txt'
[victoria@victoria out]$ ls -l
total 20
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 banana_1.txt
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 banana_2.txt
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 banana_3.txt
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 banana_4.txt
-rw-r--r-- 1 victoria victoria 6 May 23 18:13 banana.txt
[victoria@victoria out]$
解释:
- 使用
sed
正则表达式命令我捕获源文件名的三个部分,
/(.*)\.(.*)\.~([0-9]{1,})~$/
即,在序列匹配中:
- 一切:
(.*) # captured as group \1
- 时期
\.
- 一切:
(.*) # captured as group \2
- 时期
\.
- 波形符:
~
- 任意数量的数字:
([0-9]{1,}) # captured as group \3
- 第二个波形符和行尾:
~$
并重新排列它们:
/\1_\3.\2/
# 注意句点的位置,无需在此处转义`
请注意在-quoted命令`
的开头/结尾处使用反引号。"
echo
2>/dev/null
忽略任何虚假警告(如果发生)。
-v
如果您不希望命令输出详细信息,请忽略该标志mv
。
也可以看看:
答案3
好吧,不要以我不差的 bash 技能来评判我,但这个解决方案对我有用。 (我很感激字节指挥官解决方案但这是由于它的限制而不是我想要的)
所以这是我的小脚本来完成这项工作......
$2
是路径$3
文件名$punktpdf
只是“.pdf”
所以这是我的小脚本......
if [ -s $2$3$punktpdf ]; then
for i in `seq 1 100000`;
do
if [ ! -s $2$3$i$punktpdf ]; then
if mv scan.pdf $2$3$i$punktpdf; then
echo $3$i$punktpdf
exit 0
break
else
echo 1
break
fi
fi
done
else
#Regular mv
fi
答案4
我创建了move
命令。
move
如果文件存在则命令添加索引。
npm i -g @gauravnumber/move
例子
文件夹结构
.
├── 1.txt
├── 2.txt
├── 3.txt
├── 4.txt
├── 5.txt
└── 6.txt
输入以下命令。
move 1.txt 2.txt
2.txt
文件已存在。move
命令在文件上附加索引。运行以上命令后。文件夹结构如下所示。
.
├── 2_1.txt
├── 2.txt
├── 3.txt
├── 4.txt
├── 5.txt
└── 6.txt
move
命令还支持多个文件。
move *.jpg dirname
move *.png *.jpg dirname
move dirname1 dirname2
move dirname1/* dirname2
这是链接到回购协议