我需要识别音乐播放列表文件 .m3u 中包含字符串“[LD]”的行,并使用特定更改更新这些行。
例如:
/music/Miles Davis/1959 - Kind of Blue [LD]/Miles Davis - So What.mp3
需要成为:
/music/_lossless/Miles Davis/1959 - Kind of Blue/Miles Davis - So What.mp3
IE。字符串“_lossless/”插入到“/music/”之后,字符串“[LD]”从音乐文件路径中删除。
我使用 for 循环文件,因为每个文件还需要执行许多其他进程。
for f in *.m3u;
do
# I can identify the lines using:
fgrep -n "[LD]" "$f"
# I can grab the line number using:
ld_line=$(fgrep -c "[LD]" "$f")
# and have tried processing the changes using sed, but it is not working..
#sed "$ld_lines![LD]!!" "$f"
# Ive also tried using sed as follows:
sed '![LD]!s!music!music/_lossless!' "$f"
# but neither of the above approaches either work or handle both modifications
done
该解决方案不必使用 sed,无论什么都是最好的。
答案1
sed '/ \[LD\]/ { s///; s,/,/_lossless/,2; }' file
要查找文件中包含子字符串的行,您可以使用中的 [LD]
正则表达式。需要转义以失去它在正则表达式中所具有的特殊含义。我们不需要转义,但为了对称性我们会转义它。/ \[LD\]/
sed
[
]
一旦我们找到了包含子字符串的行 [LD]
,我们就可以用替换来替换该字符串,即删除它s///
。使用空正则表达式将重新使用最近的表达式,而最近的表达式是匹配的表达式 [LD]
。
下一个替换是将第二个替换/
为字符串/_lossless/
。我们/
使用末尾的 来选择该行中正则表达式的第二个匹配项2
,并且为了方便起见,我们使用逗号而不是斜杠作为命令的分隔符。
在循环中创建带有.new
文件名后缀的文件:
for name in *.m3u; do
sed '/ \[LD\]/ { s///; s,/,/_lossless/,2; }' -- "$name" >"$name".new
done
要在 macOS 上就地更改文件,请使用sed -i '' ...
.
for name in *.m3u; do
sed -i '' '/ \[LD\]/ { s///; s,/,/_lossless/,2; }' -- "$name"
done
请记住在测试破坏性命令之前备份数据。
答案2
你可以试试这个sed
for f in *.mp3; do
var1=$(sed -E 's|(.[^/]*)(.[^[]*).*](.*)|\1/_lossless\2\3|' "$f")
mv "$f" "var1"
done
输出
/music/_lossless/Miles Davis/1959 - Kind of Blue /Miles Davis - So What.mp3