使用 sed 和 mv 重命名文件

问题描述 投票:0回答:8

我想重命名以下格式的文件:

img_MM-DD-YY_XX.jpg

img_MM-DD-YY_XXX.jpg

至:

newyears_YYYY-MM-DD_XXX.jpg

地点:

  • YYYY = 年
  • MM = 月份
  • DD = 日
  • XXX 或 XX = 照片编号

我想出了这个脚本,但它不起作用:

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

任何帮助将不胜感激。

regex bash sed mv
8个回答
17
投票

你可以在 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
也得到
gnu sed
的支持。


3
投票

没有 for 循环。

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

在 mv 之前省略管道到 bash 以查看结果

感谢 http://www.gnu.org/software/sed/manual/sed.html#Rename-files-to-lower-case


1
投票

这个简单的变体对我有用:

$ 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
$

唯一的区别是使用显式的

-e
选项代替分号。

在 MacOS X 10.6.7 上测试。


0
投票

我记得曾经搞过这种事情。我发现创建一个脚本来执行您想做的事情通常很有用:

即。脚本的输出将是一个如下文件:

mv   file1 file2
mv   file3 file4
.....
mv   fileN fileM

要创建它,只需执行 ls | grep 日期模式 | sed 脚本将 mv file1 粘贴到 file2 > myscript

然后执行./myscript

这样您就可以更好地查看中间输出以找出问题所在。


0
投票

它可以通过纯粹的 bash 脚本来处理。

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

0
投票

你不需要正则表达式。只需使用重命名即可:

rename img_ newyears_ img_*.jpg

如果你想使用 mv,请使用此单行:

for filename in img*jpg; do mv -v $filename $(echo $filename | sed 's/img_/newyears_/'); done

您也可以不使用 sed 来完成:

for filename in img*jpg; do mv -v "$filename" "newyears_${filename#*_}"; done

在 CenotOS 7 中测试


-1
投票

红宝石(1.9+)

$ ruby -e 'Dir["img*jpg"].each{|x|File.rename(x,x.gsub(/img_(.*?)-(.*?)-(.*?)\.jpg/,"newyears_20\\2-\\1-\\3.jpg") )}'

-1
投票
for f in *.jpg; do
  n=$(sed -r 's/^(.+)-([^_]+)_(.+)\.jpg/\2-\1_\3.jpg/' <<< "${f#img_}")
  mv "$f" "newyears_20$n"
done

<<<
是一个
bash
功能,称为 here string,并且
${f#img_}
img_
中删除
$f
前缀。
sed
表达式通过将
img_MM-DD-YY_XX.jpg
隔离为
YY-MM-DD_XX.jpg
、将
MM-DD
隔离为
\1
、将
YY
隔离为
\2
,然后形成
XX
,将
\3
转换为
\2-\1_\3.jpg
。请注意,
n
作业中不需要引用。

为了安全起见,对于这样的事情,我实际上更喜欢使用

echo mv
而不是
mv
,这样我就可以看到它将生成的命令。然后您可以删除
echo
或将输出通过管道传输到
sh

© www.soinside.com 2019 - 2024. All rights reserved.