I want to read all files of my photo library and check if they really exist. My AppleScript knowledge is so far ok and enough to realize this. But this is about a large number of files and AppleScript is -definitely- not suitable for this. For 10,000 files, it takes 20 minutes. So I decided to do the most important parts of the script with shell scripts.... but I am quite inexperienced in the Unix world and had to complete a two day internet search crash course. However, I have now reached a point where I would like to take your help!
Here are my experiments:
I'll embed it all in an AppleScript. Since a lot of files have to be edited, I thought it would be better to save them in temporary text files between the steps. In the first step, the database is read out. It'll only take a second:
Path | Name | ID | Reference | External hard disk name
2018/03/27/20180327-122110/TVTower.JPG|TVTower|hA3CRRfPSS6FXqk7IDobLw|0|
Projekte/BCT 2017/BCT Fotos GPS/BCT_GPS_001.JPG|BCT_A_GPS_001|hyvsQgiaR4e3ou7XIZ%Gjg|1|Media
Leo/Carmina Burana/Leo UdK/IMG_0626.JPG|IMG_0626|j7342DtGSmag7YVLN1Nzhg|1|Logic
Users/spazek/Desktop/WeTransfer/Bild 2.png|Bild 2|Sa7rckZiSd2bIiRVO0JidA|1|macOS
In the next step, the missing path parts are added
/Users/spazek/Pictures/Fotos Library.photoslibrary/Masters/2018/03/27/20180327-122110/TVTower.JPG|TVTower|hA3CRRfPSS6FXqk7IDobLw|0|
/Volumes/Logic/Projekte/BCT 2017/BCT Fotos GPS/BCT_GPS_001.JPG|BCT_A_GPS_001|hyvsQgiaR4e3ou7XIZ%Gjg|1|Media
/Volumes/Logic/Leo/Carmina Burana/Leo UdK/IMG_0626.JPG|IMG_0626|j7342DtGSmag7YVLN1Nzhg|1|Logic
/Users/spazek/Desktop/WeTransfer/Bild 2.png|Bild 2|Sa7rckZiSd2bIiRVO0JidA|1|macOS
It takes 2:30 minutes with my solution for 10,000 files on my Mac. The running AppleScript seems to be at the limit of overload! Running in the Terminal.app, I see in the header of the window that there is always a jump between awk and bash... I guess there's something wrong.
In the next step I want to check the paths to see if they exist. Since it is similar to the previous script, it also takes a little longer. The last step writes missing files to a text file.
.
sqlite3 -separator $'|' /Users/spazek/Desktop/xsystx/systphotos.db 'select RKMaster.imagePath, RKMaster.name, RKMaster.uuid, RKMaster.fileIsReference, ( select RKVolume.name from RKVolume where RKVolume.modelId = RKMaster.volumeId) from RKMaster' > /Users/spazek/Desktop/filelist1.txt
.
while read f; do
var1=`echo "$f" | awk -F[=\|] '{print $1}'`;
var2=`echo "$f" | awk -F[=\|] '{print $2}'` ;
var3=`echo "$f" | awk -F[=\|] '{print $3}'` ;
var4=`echo "$f" | awk -F[=\|] '{print $4}'` ;
var5=`echo "$f" | awk -F[=\|] '{print $5}'` ;
if [ "$var4" == 0 ] ; then
echo /Users/spazek/Pictures/Fotos Library.photoslibrary/Masters/"${f}" ;
else
if [ "$var5" == "macOS" ]; then
echo /"${f}" ;
else
echo /Volumes/"$var5"/"${f}";
fi;
fi >> /Users/spazek/Desktop/filelist2.txt;
done < /Users/spazek/Desktop/filelist1.txt
.
while read f; do
var1=`echo "$f" | awk -F[=\|] '{print $1}'`;
var3=`echo "$f" | awk -F[=\|] '{print $3}'` ;
test -f "$var1" || echo "$var1|$var3" >> /Users/spazek/Desktop/filelist3.txt;
done < /Users/spazek/Desktop/filelist2.txt
.
while read f; do
var1=`echo "$f" | awk -F[=\|] '{print $1}'`;
var2=`echo "$f" | awk -F[=\|] '{print $2}'` ;
test -f "$var1" || echo "Name = $var2 \n Path = $var1 \n";
done > ~/Desktop/Photos_MissingItems.txt < /Users/spazek/Desktop/filelist3.txt
I would be very happy about help or suggestions to improve the scripts
awk
is NOT going to be any faster if you runawk
repeatedly in a loop like that, and will probably be much slower - there's a lot of overhead every time you runawk
, and shell interpreters are extremely slow at processing text files withread
. In short, your code is probably the slowest possible way to do it. You WILL see huge performance increases if you do the whole job inawk
. orperl
. orpython
. or any other scripting language if you use it to read in the entire input file itself, rather than pipe it in one line at a time in a shell loop. – cas Apr 01 '18 at 05:06while read f; do var1=
echo "$f" | cut -d"|" -f1; test -f "$var1" || echo "$f" | cut -d"|" -f1,2,3 ; done >> /Users/spazek/Desktop/filelist3.txt < /Users/spazek/Desktop/filelist2.txt
– spazek Apr 01 '18 at 15:11