2014-04-23 30 views
2

我在OSX上有一个文件夹,其中包含从在线DVR下载的电视节目。我想制作一个节目清单并将其格式化为与另一个清单相匹配以供比较。使用sed在bash脚本中进行就地重命名

当我在shell中运行以下命令时,一切正常,我得到我想要的列表。

ls *.mp4 > loaded_shows.txt 
sed -i$0 's/\(.*\)_/\1\ /' loaded_shows.txt 
sed -i$0 's/\(.*\)_/\1\ /' loaded_shows.txt 
sed -i$0 's/\(.*\)_/\1\ /' loaded_shows.txt 
cat loaded_shows.txt 

当我把同样的命令放到一个bash脚本,sed中给出了每个即使脚本是在同一目录中的文件是就地更换以下错误消息。

sed的:重命名():没有这样的文件或目录

以及物品是否完整,这里的bash脚本:

#!/bin/bash 
ls *.mp4 > loaded_shows.txt 
sed -i$0 's/\(.*\)_/\1\ /' loaded_shows.txt # replace last _ with space 
sed -i$0 's/\(.*\)_/\1\ /' loaded_shows.txt # again replace last _ with space 
sed -i$0 's/\(.*\)_/\1\ /' loaded_shows.txt # remove the file extension 
cat loaded_shows.txt 

而且样本输入文件名:

666_Park_Avenue_2014-04-22_23.35.mp4 
Americans_2014-04-20_22.45.mp4 
Scandal_2014-04-20_21.00.mp4 
The_Voice_of_USA_2014-04-22_19.30.mp4 

我怎样才能让sed在bash脚本中工作?

+0

你如何运行Bash脚本?它是否还创建loaded_shows.txt? – AsksAnyway

+1

我发现我做错了。问题在于-i参数的格式。 我在没有进一步解释的情况下看到了这个例子。我尝试了几种告诉sed不要备份文件的方法,-i $ 0是我发现的唯一一个似乎适用于OSX的例子。在发布这个问题之后阅读了更多内容之后,我意识到-i $ 0在脚本中不起作用。 我用-i''替换它(之间的空格),现在脚本工作并创建loaded_shows.txt。 一些示例建议使用-i“(无间隔),它不适用于OSX。 – user83156

+2

你打败了我。我建议'-i .bak'作为参数。 “$ 0”可能工作;它是脚本的名称,但是如果它包含'$ 0'中的路径信息,那么就会被洗掉。 –

回答

0

你已经注意到你的错误与sed的-i选项。做得好找到它。 :)

如果你的脚本中的注释是你想达到什么指示,我其实重构剧本的管道用sed,只需一次,看起来像这样:

#!/bin/bash 

for f in *.mp4; do 
    echo "$f" | sed 's/_\([^_]*\)_\([^_]*\).mp4$/ \1 \2/' 
done > loaded_shows.txt 

运行sed次数更少更经济,打开/关闭文本文件只有一次更经济。因为,你知道,毫秒浪费了毫秒。

我应该在这里指出for循环。通常,当您通过shell脚本运行文件列表时,您想要使用for而不是解析ls的输出。 Parsing ls在shell脚本世界中是一个众所周知的问题,最好不要让自己这样的坏习惯,即使在受控环境中的小脚本中也是如此。

+0

你可以进一步优化:'printf'%s \ n“* .mp4 | sed's/_ \([^ _] * \)_ \([^ _] * \)。mp4 $/\ 1 \ 2 /'> loaded_shows.txt'对所有文件名只有一个sed调用?如果任何文件名包含换行符,则可能会遇到问题;否则,我认为应该是好的。您的版本每个文件名运行一次sed;对于任意数量的文件,原始运行“sed”三次(如果有超过三个文件,则为其胜出;如果少于三个文件,则胜出)。无论文件数量如何,我建议的修订版本都会运行一次'sed'。 –

+0

非常感谢这件事,就像魅力一样,Jonathans的建议更加简化了脚本。 我想知道如何更有效地做sed替换,但无法弄清楚自己。我只知道替换一个单独的事件,但用一个命令替换三件事是超出我的知识的。 你们中的任何一个都可以分解sed,这样我就可以学习sed在这些例子中的工作原理了吗? – user83156