2013-07-13 225 views
2

我想這個代碼:爲什麼這個bash for循環慢?

for f in jobs/UPDTEST/apples* ; do 
    nf=`echo $f | sed s:jobs\/::g` 
    echo $nf | tr '_' ' ' 
done > jobs 

有750個apples*類型的文本文件。但是,因爲我只是搞亂了文件名 - 我以爲它應該很快 - 但需要大約5分鐘。

有沒有其他方法可以做到這一點?

+0

爲什麼你不使用=== ls jobs/UPDTEST/apples * | sed -e's:。* apples:apples:g; s/_// g'> jobs ===?當然,你這樣做的方式遠沒有效率,至少因爲你使用了很長的參數列表,並且調用了「sed」和「tr」第n次,嵌套管道以及其他任何東西。你太複雜了。 –

+0

這很慢,因爲管道的「forks」代價很高,每次迭代最多可分成四個進程。分叉只是爲了改變一些人物,就像在平板車上交付雜貨一樣。任何想要避免分支的shell程序員都必須知道shell的內置工具箱。 – Jens

+1

@PiotrWadas你的建議很好地適用於輕微的變化:ls -d jobs/UPDTEST/apples * | sed -e's:jobs \/:: :: g; s/_// g'> jobs謝謝 – ManInMoon

回答

3

您可以使用parameter expansions${parameter/pattern/string}擺脫sedtr的呼叫。在你的情況下,它可能看起來像:

for f in jobs/UPDTEST/apples*; do 
    f=${f//jobs\//} 
    echo ${f//_/ } 
done > jobs 
+0

這裏有各種不錯的答案。所以我選擇這個,因爲我可能會使用它或PiotrWadas版本的註釋 – ManInMoon

1

首先,cd jobs將消除對sed

其次需要,你不需要tr在bash變量的值來代替字符。第二,find你根本不需要循環。

f=$(cd jobs; find UPDTEST -name 'apples*' -depth 1) 
echo "${f//_/ }" > jobs.log 

順便說一句,你不能有一個jobs目錄和文件jobs在同一目錄下。

+1

使用'f = $(cd jobs; find ...)'你甚至可以保存'cd ..'。 – Jens

+0

@Jens - 你是對的!我編輯我的答案以包含您的評論。 – mouviciel