Using Terminal to truncate filenames in directory

terminal

I have about a thousand jpegs in a directory that have filenames such as

1300-Kazoo-Pkg.jpg
1314-Learn-to-Play-Piano-withKid.jpg
1314-Learn-to-Play-Piano.jpg

I want to shorten them to the numbers before the first hyphen.

I have tried using for f in *.jpg; do mv "$f" "${f/-*.}"; done but I can't figure out what to add to get done what I want done.

Any suggestions?

Best Answer

To preserve the filename extension in the expected way, you should instead do this:

for f in *.jpg; do mv "$f" "${f/-*}.jpg"; done

That is, use ${f/-*}.jpg instead of ${f/-*.}.

To deal with the case of multiple files that have the same prefix before the dash, you can do something like this: [Note: For a better version, see the Update I’ve since added after this.]

i=0
for f in *.jpg; do
  if [ "$(ls -l ${f/-*}* | wc -l | xargs)" -gt 1 ]; then
    for g in "${f/-*}"; do
      mv "$f" "$g-$((i++)).jpg"
    done
  else
    if [[ $f == *"-"* ]]; then
      mv "$f" "${f/-*}.jpg"
    fi
  fi
done

That will give you output like this:

1300.jpg
1314-0.jpg
1314-1.jpg
1315-2.jpg
1315-3.jpg

That is, a -N suffix will get added, though with the limitation that this simple example just keeps incrementing the N value across the whole set of files instead of per-prefix.

Also note that you can safely re-run this script multiple times in the same directory and you’ll end up with the same expected filenames in the end (which I think is what you’d want, rather than it monkeying around further with any filenames that are already in the form you want).


Update

Here’s a better version that just appends 1-N suffixes to the renamed files if it finds an existing file with the same basename or same basename+N (in which case it increments by N+1 and retries).

for f in *.jpg; do
  base=${f/-*}
  if [[ -e "${base}.jpg" ]] ; then
    i=1
    while [[ -e "${base}-${i}.jpg" ]]; do
      let i++
    done
    base=$base-$i
  fi
  mv "$f" "${base}.jpg"
done

That gives output like this:

1300.jpg
1314-1.jpg
1314.jpg
1315-1.jpg
1315-2.jpg
1315.jpg