2014-04-23 61 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