我有几千个以下形式的文件:
[8位数字]_[我想要的号码]_S60491_I129111.dcm。
我希望删除除我想要的数字之外的所有内容,并将其用作其名称。在 Ruby 中,我可以使用正则表达式获取该值/^.*_(\d+)_S60491_I12911.dcm/
,但我无法将其转换为sed
允许我用下划线之间的数字替换完整文件名的表达式。
有没有办法使用sed
或其他基本 Bash 命令来做我想做的事情?如果有帮助的话,我想要的数字只是一个计数器(即从 1 到 2100),并且前缀 8 位数字恰好导致文件按正确顺序列出(即从文件 1 到文件 2100),所以我可能想得太多了。
答案1
这对我有用:for a in * ; do mv "$a" $(echo "$a" | cut -d'_' -f 2) ; done
蟾蜍:/home/hennes/work/foo>ls -l 共 0 -rw------- 1 个用户 0 1 月 23 日 22:19 12345678_023454_S60491_I129111.dcm -rw------- 1 个用户 0 1 月 23 日 22:19 12345678_123454_S60491_I129111.dcm -rw------- 1 个用户 0 1 月 23 日 22:19 12345678_123456_S60491_I129111.dcm toad:/home/hennes/work/foo>for a in *;执行 mv $a $(echo $a | cut -d'_' -f 2);完成 蟾蜍:/home/hennes/work/foo>ls -l 共 0 -rw------- 1 个用户 0 1 月 23 日 22:23 023454 -rw------- 1 个用户 0 1 月 23 日 22:23 123454 -rw------- 1 个用户 0 1 月 23 日 22:23 123456
for a in *
选择所有文件。如果文件较多,可以使用 *.dcm 代替。
mv(移动)改变文件名
来自 $a (选择的文件名)
到名称的字段2,_
使用字段分隔符。
请注意,此脚本将移动文件,因此旧文件名将丢失。您可以使用“cp”而不是“mv”来制作副本。
如果要保留扩展名,请将其添加到 -f 2) 之后。
例如
for a in * ; do cp $a $(echo $a | cut -d'_' -f 2).dcm ; done
答案2
有一种工具通常名为改名或prename
安装在大多数系统上。在我的 Debian/Ubuntu 系统上,它是 Perl 的一部分。它允许您使用 Perl 样式的正则表达式以您喜欢的方式操作文件名。
您的命令可能看起来像这样。我建议您--no-act
在实际进行任何更改之前传递该选项并检查输出。
prename 's/^.*_(\d+)_S60491_I12911.dcm/$1/' *
答案3
因为我们知道名称的格式并且不包含空格:
for a in * ; do
mv $a $(echo $a | sed 's/[^_]*_//;s/_S60491_I129111.dcm//')
done
答案4
有很多方法可以完成此操作。但是既然您要求了sed
,那么可以这样做:
lsdcm | sed 's/^([0-9]{8}_([0-9])_S60491_I129111.dcm)/mv \1 \2 /g' | bash
模式的第一位选择 8 位数字,然后查找任何数字(因为您没有提到第二个数字的大小),然后查找尾随序列。\1
并\2
引用外部和内部转义括号的内容\(...\)
。在这种情况下,您可以用任何 shell 替换bash
。
sed 的 GNU 扩展还允许您执行以下操作:
ls *dcm | sed 's/^([0-9]{8}_([0-9]+)_S60491_I129111.dcm)/mv \1 \2 /g' | bash
where+
允许匹配一个或多个,而 where*
匹配零个或多个,这会给 带来问题12345678__S60491_I129111.dcm
。