1

I have a series of directories, and images contained within:

/Volumes/library/Originals/2012/2012-05-13 Event/filename.jpg
/Volumes/library/Originals/2011/2011-03-11 Event/filename.jpg
/Volumes/library/Originals/2011/2011-01-12 Event/filename.jpg
/Volumes/library/Originals/2009/2019-07-11 Event/filename.jpg

Using bash, how can I create symbolic links to this directory tree in a single directory?

/image-links/filename.jpg
/image-links/filename1.jpg

I need this to get my photos screen saver running on Mac OS X 10.8 which doesn't support recursive directories. I figure I can make a cron job that does this nightly. Thanks for your help.

ensnare
  • 40,069
  • 64
  • 158
  • 224
  • 2
    Do not cross-post on different [SE] sites. If a question should be on a different site please Flag it so a moderator can take care of it. – Chris S Aug 06 '12 at 14:11
  • 1
    We'll go ahead and keep this one open, since the SF copy was closed and it is getting answered here. In the future, please don't cross-post. – Bill the Lizard Aug 06 '12 at 14:23

4 Answers4

3

Give this a crack:

#!/bin/sh

seq=1
for f in $(find /Volumes/library/Originals -name *.jpg)
do
    base=$(basename "$f" .jpg)
    new=$(printf "%s%03d.jpg" "$base" $seq)
    ln -fs "$file" "/image-links/$new"
    seq=$(expr $seq + 1)
done
trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • 2
    This'll fail on paths containing whitespace. Never combine for and find. See http://mywiki.wooledge.org/BashFAQ/020 – geirha Aug 06 '12 at 15:45
  • In bash and ksh `seq=$((seq+1))` or even (( seq++ )) would look better -- concise, no external commands, hence slightly faster. Not that it matters for 10 files, but every bit counts. – Henk Langeveld Aug 06 '12 at 15:45
1
PREFIX="filename"
SOURCEDIR="/Volumes/library/Originals"
DESTDIR="image-links"

i=0
cd $DESTDIR
find "$SOURCEDIR" -name \*.jpg | while read f
do
  ln -s "$f" $PREFIX$i.jpg
  i=$((i+1))
done
Igor Chubin
  • 61,765
  • 13
  • 122
  • 144
1

This oneliner is working on linux very well.

find /Volumes/library/Originals -name "*.jpg" |
    awk '{print "ln -s \""$0"\" /image-links/filename_"FNR".jpg"}' | sh

To explain the pipes

first finds files | second makes commands |third runs commands

Pretty simple, tested and working in cron.

Petr

Philip Kearns
  • 377
  • 4
  • 14
Petr Matousu
  • 3,120
  • 1
  • 20
  • 32
0

Assuming the files are in the same depth, a for-loop like this should do:

i=1
for file in /Volumes/library/Originals/*/*/*.jpg; do
    base=${file##*/}
    ln -s "$file" "/image-links/${base%.*}$((i++)).jpg"
done

Instead of giving the links an incrementing number, you could add the directory name to the linkname instead.

for file in /Volumes/library/Originals/*/*/*.jpg; do
    base=${file##*/}
    dir=${file%/*} dir=${dir##*/}
    ln -s "$file" "/image-links/$dir $base"
done
geirha
  • 5,801
  • 1
  • 30
  • 35