私は1年間、すべての写真のシンボリックリンクを生成するシェルスクリプトを持っています。写真は他のカメラからインポートされ、サブディレクトリにあります。
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
この問題に対する別の解決策が見つかりました。
各ファイル名が一意になるように(IMG番号+日付)、他のカメラの写真名を正常に変更しました(find
および使用)。exiv2
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
使用に固執する場合)。絶対に使用しないでください:シェルフラグメント内でファイル名をシェルスクリプトに直接挿入するため、シェル構文で解析され、ファイル名にシェル構文で特別な意味を持つ文字が含まれていると競合が発生します。常に別々のパラメータとして渡されます。… {} \;
{}
{}
find -exec
{}
コード(テストされていません):
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" {} +