在shell脚本中包含awk会使输出为空?

时间:2016-02-15 16:19:29

标签: bash shell awk

我制作了一个shell脚本,我可以使用我的播放列表来制作MPD。我按照我想要的方式按文件夹和艺术家来编写歌曲,但是当我尝试使用awk删除脚本末尾的重复项时,输出变为空。

继承剧本:

(
mpc search artist 'Black Coast' &&
mpc search artist 'ASTR' &&
ls ~/music/HDD/Chill | awk '$0="HDD/Chill/"$0'
) | tee testi.txt;
awk '!v[$0]++' testi.txt | tee testi.txt

上面的awk正确地为字符串加前缀,但是如果我在输出下面添加awk是一个空文件。然而,该行在脚本文件之外工作。

编辑:它适用于

(
mpc search artist 'Black Coast' &&
mpc search artist 'ASTR' &&
ls ~/music/HDD/Chill | awk '$0="HDD/Chill/"$0'
) | awk '!v[$0]++' | tee testi.txt

所以我问问题改为为什么上面的例子不起作用?

2 个答案:

答案 0 :(得分:0)

您正在写入您正在阅读的同一个文件。永远不要这样做,因为shell在阅读它之前可以写它。你想要这样的SOMETHING(未经测试):

(awk '!v[$0]++' testi.txt | tee tmp.txt) && mv tmp.txt testi.txt

答案 1 :(得分:0)

我想这里的问题是您的输入和输出文件是相同的。这将导致在awk可以从中读取之前将其截断以进行写入。

我建议这样做:

(
    mpc search artist 'Black Coast' &&
    mpc search artist 'ASTR' &&
    ls ~/music/HDD/Chill | awk '$0="HDD/Chill/"$0'
) | awk '!v[$0]++' | tee testi.txt

这样,输出文件只触摸一次。

另外,我真的不喜欢ls行的外观 - 我建议使用这样的内容:

( cd ~/music && printf '%s\n' HDD/Chill/* )

这会创建一个额外的子shell,但不需要外部子shell,因此您可以将命令更改为:

{
    mpc search artist 'Black Coast' &&
    mpc search artist 'ASTR' &&
    ( cd ~/music && printf '%s\n' HDD/Chill/* )
} | awk '!v[$0]++' | tee testi.txt

如果您的文件名包含换行符,则会失败(但是,您的原始方法也会如此)。