我有一个 shell 脚本,用于创建一年中所有照片的符号链接。这些照片来自不同的相机,位于子目录中。
f=$(pwd);
export f;
q="2015/";
z="2015_Links/";
find $q/. \( -name "*.CR2" -o -name "*.JPG" \) -execdir sh -c 'ln -s "$PWD"/$(basename {}) "$f"/"$z"/Link_$(basename {})' {} \;
某些照片具有相同的文件名,导致错误:
ln: failed to create symbolic link ‘2015_Links/Link_IMG_1588.CR2’: File exists
在这种情况下,我想重命名这些现有文件。例如,Link_IMG_1588.CR2
到Link_IMG_1588A.CR2
.
答案1
我找到了该问题的另一种解决方案。
我成功地从不同的相机重命名了我的照片(使用find
和exiv2
),以便每个文件名都是唯一的(IMG 编号 + 日期):
find 2015/. \( -name "*.CR2" -o -name "*.JPG" \) -execdir sh -c 'exiv2 -r':basename:_%Y%m%d_%H_%M_%S' rename $(basename {})' {} \;
答案2
战略:
- 测试理想的目标文件名是否存在。
- 如果是,请尝试添加数字后缀
-1
、-2
等。
其他改进:
- 使用
-exec … {} +
而不是-execdir … {} \;
稍微提高性能。您实际上不需要-execdir
这里,因为您正在建立绝对链接。 - 使用
$x
(或者$1
如果您坚持使用… {} \;
)而不是{}
在内壳中。切勿{}
在 shell 代码段内使用find -exec
: ,它将文件名直接插入到 shell 脚本中,因此它会被解析为 shell 语法,如果文件名包含任何在 shell 语法中具有特殊含义的字符,则会崩溃。始终{}
作为单独的参数传递。
代码(未经测试):
find "$q/." \( -name "*.CR2" -o -name "*.JPG" \) -exec sh -c '
for x; do
base=$0/Link_${x##*/}; base=${base%.*}; ext=${x##*.}
if [ -e "$target.$ext" ]; then
suffix=1;
while [ -e "${base}-$suffix.$ext"; do suffix=$((suffix+1)); done
fi
ln -s -- "$PWD/${x##*/}" "$target"
done
' "$PWD/$z" {} +