问题
I want to rename files in the format:
img_MM-DD-YY_XX.jpg
img_MM-DD-YY_XXX.jpg
to:
newyears_YYYY-MM-DD_XXX.jpg
Where:
- YYYY = year
- MM = month
- DD = day
- XXX or XX = photo number
I came up with this script but it isn't working:
for filename in ?*.jpg; do
newFilename=$(echo $filename | \
sed 's/img_\(.*\)-\(.*\)-\(.*\)_\([0-9][0-9]\)\./newyears_20\3-\1-\2_0\4./;
s/img_\(.*\)-\(.*\)-\(.*\)_\([0-9][0-9][0-9]\)/newyears_20\3-\1-\2_\4/' -)
mv $filename $newFilename
done
Any help would be greatly appreciated.
回答1:
You can try this script in bash:
for filename in *.jpg; do
newFilename=$(sed -E 's#img_([0-9]{1,2})-([0-9]{1,2})-([0-9]{1,2})_(.*)$#newyears_20\3-\2-\1_\4#' <<< "$filename")
mv "$filename" "$newFilename"
done
sed -E
is supported by gnu sed
also.
回答2:
Without a for loop.
ls | grep 'jpg$' | sed '
#Save the original filename
h
#Do the replacement
s/img_\(.*\)-\(.*\)-\(.*\)_\([0-9][0-9]\)\./newyears_20\3-\1-\2_0\4.//
s/img_\(.*\)-\(.*\)-\(.*\)_\([0-9][0-9][0-9]\)/newyears_20\3-\1-\2_\4//
#Bring the original filename back
x
G
s/^\(.*\)\n\(.*\)$/mv "\1" "\2"' | bash
Ommit piping to bash to see the results before mv
Thanks to http://www.gnu.org/software/sed/manual/sed.html#Rename-files-to-lower-case
回答3:
I remember messing around with this sort of thing. I found it often useful to create a script that you execute to do what you want:
ie. output of your script would be a file like:
mv file1 file2
mv file3 file4
.....
mv fileN fileM
To create this, just do a ls | grep date pattern | sed script to stick mv file1 to file2 > myscript
then just execute ./myscript
This way you have a better look at the intermediate output to figure out what's going wrong.
回答4:
This trivial variant works for me:
$ cat mapper
for filename in ?*.jpg
do
newFilename=$(echo $filename | \
sed -e 's/img_\(.*\)-\(.*\)-\(.*\)_\([0-9][0-9]\)\./newyears_20\3-\1-\2_0\4./' \
-e 's/img_\(.*\)-\(.*\)-\(.*\)_\([0-9][0-9][0-9]\)/newyears_20\3-\1-\2_\4/')
echo mv $filename $newFilename
done
$ echo > img_04-23-09_123.jpg
$ echo > img_08-13-08_33.jpg
$ sh mapper
mv img_04-23-09_123.jpg newyears_2009-04-23_123.jpg
mv img_08-13-08_33.jpg newyears_2008-08-13_033.jpg
$
The only difference is the use of the explicit -e
options in place of a semi-colon.
Tested on MacOS X 10.6.7.
回答5:
It could be handled by a purely bash script.
for j in ?*.jpg
do
n="newyears_20${j:10:2}-${j:4:2}-${j:7:2}";
if [ ${j:15:1} = "." ];then
n="${n}_0${j:13}"
else
n="${n}${j:12}"
fi
mv $j $n
done
回答6:
Ruby(1.9+)
$ ruby -e 'Dir["img*jpg"].each{|x|File.rename(x,x.gsub(/img_(.*?)-(.*?)-(.*?)\.jpg/,"newyears_20\\2-\\1-\\3.jpg") )}'
回答7:
for f in *.jpg; do
n=$(sed -r 's/^(.+)-([^_]+)_(.+)\.jpg/\2-\1_\3.jpg/' <<< "${f#img_}")
mv "$f" "newyears_20$n"
done
The <<<
is a bash
feature called a here string and ${f#img_}
removes the img_
prefix from $f
. The sed
expression turns img_MM-DD-YY_XX.jpg
into YY-MM-DD_XX.jpg
by isolating MM-DD
into \1
, YY
into \2
and XX
into \3
then forming \2-\1_\3.jpg
. Note that no quoting is required in the n
assignment.
For safety, for things like this I actually prefer to use echo mv
instead of mv
, so I can see the command this would generate. Then you can remove echo
or pipe the output to sh
.
来源:https://stackoverflow.com/questions/5671773/rename-files-using-sed-and-mv