我遇到这种情况,不同的子文件夹中有很多名称相似的文件(但它们都遵循某种模式)
file1
file1 (Copy)
/folder1/file2.txt
/folder1/file2 (Copy).txt
/folder1/file3.png
/folder1/file3 (Copy).png
每个文件都位于其副本的同一文件夹中,并且具有相同的扩展名,不同之处在于它(Copy)
在名称末尾
我想获取所有这些文件并删除最旧的一个,然后最终将文件重命名为,例如,如果需要重命名,则将其重命名file1 (Copy)
为file1
(即删除后缀)。(Copy)
我正在考虑使用find
andmv
但我不知道如何告诉它移动最近的一个。
答案1
扩展find
+bash
解决方案(还需要 GNU 实现stat
):
find . -type f -name "* (Copy).*" -exec bash -c 'p="${0%/*}"; bn="${0##*/}";
main_bn="${bn/ (Copy)/}";
if [ -f "$p/$main_bn" ]; then
t_copy_file=$(stat -c %Y "$0"); t_main_file=$(stat -c %Y "$p/$main_bn");
if [[ $t_copy_file -gt $t_main_file ]]; then
mv "$0" "$p/$main_bn";
else
rm "$0";
fi;
fi' {} \;
p="${0%/*}"
- 基本名称被修剪的文件路径/路径bn="${0##*/}"
- 文件的基本名称main_bn="${bn/ (Copy)/}"
-(Copy)
从基本名称中删除子字符串以获得主要/公共基本名称if [ -f "$p/$main_bn" ]
- 如果主要/原始文件存在(并且在符号链接解析后发现是常规文件)t_copy_file=$(stat -c %Y "$0")
- 获取找到的最后修改时间“复制”文件t_main_file=$(stat -c %Y "$p/$main_bn")
- 获取最后修改时间原来的文件if [[ $t_copy_file -gt $t_main_file ]]
- 如果“复制”文件是最近的文件 - 将其移至原来的一个(使它原来的) 和mv "$0" "$p/$main_bn"
- 否则 - 的原来的文件是最新的,删除“复制“ 文件与
rm "$0"
-nt
或者使用文件测试运算符更短一些( [ newerfile –nt olderfile ]
- 检查是否newerfile
比 更晚更改olderfile
,或者是否newerfile
存在且不olderfile
存在):
find . -type f -name "* (Copy).*" -exec bash -c 'p="${0%/*}"; bn="${0##*/}";
main_bn="${bn/ (Copy)/}";
if [ -f "$p/$main_bn" ]; then
if [ "$0" -nt "$p/$main_bn" ]; then
mv "$0" "$p/$main_bn";
else
rm "$0";
fi;
fi' {} \;
答案2
使用以下方法可能会更容易zsh
:
setopt extendedglob # best in ~/.zshrc
for file (./**/?*" (Copy)"*(ND.)) {
base=$file:h/${${file:t}/" (Copy)"}}
[[ ! -f $base || -L $base ]] ||
if [ $file -nt $base ]; then
mv $file $base
else
rm -f $file
fi
}
您可能需要先检查是否没有file (Copy) (Copy).txt
文件。
**/
: 任何级别的子目录N
:空球如果没有匹配则展开为空而不是出错D
:包括隐藏文件(D
ot 文件)并下降到隐藏目录。.
: 只包括常规的文件(无目录、fifo、设备、符号链接...)$file:h
:头文件(目录部分)的,如csh
$file:t
:尾巴(文件名部分)${var/pattern/replacement}
,这里没有替换[[ ! -f $base || -L $base ]] ||...
跳过非常规文件或符号链接(即使它们指向常规文件)作为保护措施。[ $file -nt $base ]
$file
: 如果最后修改则返回 true后$base
(或者$base
无法访问,我们不应该在上述检查之后发生)。