I was using a code to rename files and a very interesting problem emerged: It worked in a computer running Mac OSX Lion 10.7.5, but it failed on Mac OSX 10.6.8 Snow Leopard.
The code is:
for i in *; do mv $i `echo $i | sed 's/..//'`; done
and the error I got is:
usage: mv [-f | -i | -n] [-v] source target
mv [-f | -i | -n] [-v] source ... directory
It's very weird because mv is working normally if not in a for
loop...
Anyone know what should I do to get it working?
If you have files with spaces (or certain other shell metachaarcters) it's critical that you put all variable references in double-quotes. Otherwise, if you have e.g. i="File Name.txt"
, you'll be running a command like mv File Name.txt le Name.txt
and it'll think you're specifying 4 filenames not just 2. The other standard mistake (which you're not making) is using for file in $(ls)
, which gets confused by spaces before the names even make it into the variable.
Also, I'm a bit concerned about short filenames and name conflicts. Even if you think you don't have any short filenames, if you have the dotglob shell option set you'll wind up trying to rename the pseudo-files "." and "..", which won't go well at all. Also, if you have e.g. files named "abcdefg" and "cdefg", the script will rename the first over the second (silently erasing the second), then rename that to "efg".
So, here's my proposed rewrite (also using @TrueY's suggestion for shortening the filename):
for i in *; do
if [ ${#i} -le 2 ]; then
echo "$i: not renamed (too short)" >&2
elif [ -e "${i:2}" ]; then
echo "$i: not renamed (${i:2} already exists)" >&2
else
mv "$i" "${i:2}"
fi
done