用于删除目录中多个文件名末尾的“x”个字符的 Bash 脚本?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17751498/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 05:58:13  来源:igfitidea点击:

Bash script to remove 'x' amount of characters the end of multiple filenames in a directory?

linuxbashunixsed

提问by user2600230

I have a list of file names in a directory (/path/to/local). I would like to remove a certain number of characters from all of those filenames.

我有一个目录 ( /path/to/local)中的文件名列表。我想从所有这些文件名中删除一定数量的字符。

Example filenames:

示例文件名:

iso1111_plane001_00321.moc1
iso1111_plane002_00321.moc1
iso2222_plane001_00123.moc1

In every filename I wish to remove the last 5 characters before the file extension.

在每个文件名中,我希望删除文件扩展名前的最后 5 个字符。

For example:

例如:

iso1111_plane001_.moc1
iso1111_plane002_.moc1
iso2222_plane001_.moc1

I believe this can be done using sed, but I cannot determine the exact coding. Something like...

我相信这可以使用 来完成sed,但我无法确定确切的编码。就像是...

for filename in /path/to/local/*.moc1; do
    mv $filname $(echo $filename | sed -e 's/.....^//');
done

...but that does not work. Sorry if I butchered the sedoptions, I do not have much experience with it.

...但这不起作用。对不起,如果我屠杀了这些sed选项,我对此没有太多经验。

回答by Zoltán Haindrich

 mv $filname $(echo $filename | sed -e 's/.....\.moc1$//');

or

或者

 echo ${filename%%?????.moc1}.moc1

%% is a bash internal operator...

%% 是一个 bash 内部操作符...

回答by Cory Klein

This sedcommand will work for all the examples you gave.

sed命令适用于您提供的所有示例。

sed -e 's/\(.*\)_.*\.moc1/_.moc1/'

However, if you just want to specifically "remove 5 characters before the last extension in a filename" this command is what you want:

但是,如果您只想专门“删除文件名中最后一个扩展名之前的 5 个字符”,则此命令就是您想要的:

sed -e 's/\(.*\)[0-9a-zA-Z]\{5\}\.\([^.]*\)/./'

You can implement this in your script like so:

您可以像这样在脚本中实现它:

for filename in /path/to/local/*.moc1; do

    mv $filename "$(echo $filename | sed -e 's/\(.*\)[0-9a-zA-Z]\{5\}\.\([^.]*\)/./')";

done

First Command Explanation

第一个命令解释

The first sedcommand works by grabbing all characters until the first underscore: \(.*\)_

第一个sed命令的工作原理是抓取所有字符,直到第一个下划线:\(.*\)_

Then it discards all characters until it finds .moc1: .*\.moc1

然后它丢弃所有字符,直到找到.moc1.*\.moc1

Then it replaces the text that it found with everything it grabbed at first inside the parenthesis: /\1

然后它用它最初在括号内抓取的所有内容替换它找到的文本: /\1

And finally adds the .moc1extension back on the end and ends the regex: .moc1/

最后.moc1在末尾添加扩展并结束正则表达式:.moc1/

Second Command Explanation

第二个命令解释

The second sedcommand works by grabbing all characters at first: \(.*\)

第二个sed命令首先抓取所有字符:\(.*\)

And then it is forced to stop grabbing characters so it can discard five characters, or more specifically, five characters that lie in the ranges 0-9, a-z, and A-Z: [0-9a-zA-Z]\{5\}

然后它被迫停止抓取字符,以便它可以丢弃五个字符,或者更具体地说,五个位于 0-9、az 和 AZ 范围内的字符: [0-9a-zA-Z]\{5\}

Then comes the dot '.'character to mark the last extension : \.

然后是'.'标记最后一个扩展名的点字符:\.

And then it looks for all non-dot characters. This ensures that we are grabbing the lastextension: \([^.]*\)

然后它会查找所有非点字符。这确保我们正在获取最后一个扩展名:\([^.]*\)

Finally, it replaces all that text with the first and second capture groups, separated by the .character, and ends the regex: /\1.\2/

最后,它用第一个和第二个捕获组替换所有文本,由.字符分隔,并结束正则表达式:/\1.\2/

回答by potong

This might work for you (GNU sed):

这可能对你有用(GNU sed):

sed -r 's/(.*).{5}\././' file