Rename files using sed and mv

核能气质少年 提交于 2020-07-18 04:06:22

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!