【问题标题】:How to escape special characters?如何转义特殊字符?
【发布时间】:2012-04-14 00:16:35
【问题描述】:

我正在尝试通过 bash shell for 循环删除歌曲,但要删除这样的文件

while read item; do rm "$item"; done < duplicates

不断关注歌曲名称。有可能解决这个问题吗?我的歌曲名称可能如下所示:

/home/user/Music/Master List's Music/iTunes/iTunes\ Music/John\ Mayer/Room\ for\ Squares\ \[Aware\]/07\ 83.m4a
/home/user/Music/Master List's Music/bsg\ season\ 1\ \(Case\ Conflict\ 1\)/06\ A\ Good\ Lighter.mp3
/home/user/Music/Master List's Music/Nino\ Rota/The\ Godfather\ Pt.\ 3/14\ A\ Casa\ Amiche.m4a

如您所见,为了删除一个项目,我可以没有 %.()[] 或其他任何内容而不会被转义,除非它是 .在文件扩展名之前。有没有办法可以转义这样的特殊字符?

例如,我使用 sed 将 %20 转换为空格:

cat duplicates | sed 's/%20/\\ /g' > clean_duplicates

我正在寻找的输出如下所示:

/home/user/Music/Master\ List\'s\ Music/iTunes/iTunes Music/John\ Mayer/Room\ for\ Squares\ \[Aware\]/07\ 83.m4a
/home/user/Music/Master\ List\'s\ Music/bsg\ season\ 1\ \(Case\ Conflict\ 1\)/06\ A\ Good\ Lighter.mp3
/home/user/Music/Master\ List\'s\ Music/Nino\ Rota/The Godfather\ Pt\.\ 3\/14\ A\ Casa\ Amiche.m4a

【问题讨论】:

  • 你能确定foo%20bar 和foo bar 这两个文件真的是重复的吗? IE。完全相同的文件,这样您就可以自信地吹走foo%20bar 而不会丢失任何东西?
  • 或者你是说重复文件包含百分比编码的名称,但文件系统中的文件没有这样的名称?
  • @Kaz,一个可靠的问题...我正在使用 Banshee 的 banshee.db 文件,该文件已经为所有内容编制索引,而我列出的那些文件名实际上是包含所有曲目的表中的 URI。

标签: shell command-line sed


【解决方案1】:

更新解决实际的 url 解码问题(我之前错过了):

while read line; do printf "$(echo -n $line | sed 's/\\/\\\\/g;s/\(%\)\([0-9a-fA-F][0-9a-fA-F]\)/\\x\2/g')\n"; done < input

输出:

/home/user/Music/Master List's Music/iTunes/iTunes Music/John Mayer/Room for Squares [Aware]/07 83.m4a
/home/user/Music/Master List's Music/bsg season 1 (Case Conflict 1)/06 A Good Lighter.mp3
/home/user/Music/Master List's Music/Nino Rota/The Godfather Pt. 3/14 A Casa Amiche.m4a

所以为了删除这些文件,例如将清理后的输出重定向到文件:

while read line
do 
    printf "$(echo -n $line | sed 's/\\/\\\\/g;s/\(%\)\([0-9a-fA-F][0-9a-fA-F]\)/\\x\2/g')\n"
done < duplicates > cleaned_duplicates

while read file; do rm -v "$file"; done < cleaned_duplicates

如果您喜欢使用 explicit shell 字符转义将名称存储到脚本文件中,您可以这样做

while read file; do printf "rm -v %q\n" "$file"; done < cleaned_duplicates > script.sh

这应该导致script.sh 包含:

rm -v /home/user/Music/Master\ List\'s\ Music/iTunes/iTunes\ Music/John\ Mayer/R
rm -v /home/user/Music/Master\ List\'s\ Music/bsg\ season\ 1\ \(Case\ Conflict\ 
rm -v /home/user/Music/Master\ List\'s\ Music/Nino\ Rota/The\ Godfather\ Pt.\ 3/

【讨论】:

  • 我以两种方式运行你的,1. 你在上面写的,它似乎在我的终端崩溃之前回显了很多行,2. 只是运行你的 sed 命令,似乎唯一的区别是%20 被替换为 \x20 等等。
  • 为了排除复制/粘贴错误,我复制了我在历史记录中实际拥有的行:它对我有用:)
  • 是的!我不确定它是如何工作的,但它确实摆脱了 url 解码位。 @sehe,您是否偶然知道如何在 '()[]./ 之类的字符和空白字符前转义/放置反斜杠?告诉 bash 删除目录名或文件名中包含任何字符的文件将会崩溃且不起作用。
  • @BrandonMinton 具有讽刺意味的是,那个位在the first version of the answer 中。但是,我认为如果你做得好,你就不需要它。我已经更新了答案。哦,还有don't forget to upvote helpful answers, and accept the answer that answers your question
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-01
  • 2019-01-29
  • 2018-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多