背景:我试图查找 xml 文件中提到的音乐文件来组织我的音乐播放列表。我正在编写一个脚本,从 xml 标记中提取文件名以自动查找文件。
我的音乐位于$musicroot
,因此我find
在那里发布。但由于字符问题,我找不到以下文件[]
。
find $musicroot -name "R. Kelly - Step In The Name Of Love [mp3clan.com].mp3" -type f
没有返回任何内容,但如果我退出,[]
它就会起作用。
find $musicroot -name "R. Kelly - Step In The Name Of Love \[mp3clan.com\].mp3" -type f
/mnt/Data/Dynamic/Multimedia/Music/Not Desi/Party/R. Kelly - Step In The Name Of Love [mp3clan.com].mp3
请注意,在我的脚本中,歌曲文件在歌曲循环中迭代并存在于变量中$song
。不确定这是否有区别。
我真的很想能够直接将文件名传入我的脚本中,而不必担心像这样的转义字符,但我似乎无法在网上找到任何相关信息。可能是因为find 是一个很常见的英语单词,find
很难搜索。find
这可能吗?
答案1
如果您只是在寻找这个文件,那么只使用 bash 就可以完成:
shopt -s globstar
printf "%s\n" "$musicroot"/**/"R. Kelly - Step In The Name Of Love [mp3clan.com].mp3"
在 bash 中,globstar
允许使用**
递归通配符。当然,一旦文件名被引号括起来,bash 就不会再对其进行通配符扩展(因此,您$musicroot
也应该将其括起来)。
答案2
bash shell 的printf
内置命令有一个%q
格式说明符,
%q causes printf to output the corresponding argument in a format that can be reused as shell input.
从文档中无法完全清楚“重用为 shell 输入”的具体含义,但是它至少转义了命令find
参数中特殊的空格和通常的文件名生成(glob)字符-name
:
$ x="fo*o [ba?r]"
$ printf '%q\n' "$x"
fo\*o\ \[ba\?r\]
所以你可以尝试
song="R. Kelly - Step In The Name Of Love [mp3clan.com].mp3"
find dir -name "$(printf '%q' "$song")"
请注意,如果您有 zsh,您可以使用其q
参数扩展标志更直接地执行相同操作:
~ % song="R. Kelly - Step In The Name Of Love [mp3clan.com].mp3"
~ % find dir -name $song:q
dir/bar/R. Kelly - Step In The Name Of Love [mp3clan.com].mp3
(bash shell 具有表面上类似的@Q
扩展标志,但是其操作方式不同 - 本质上只是硬引用整个字符串。)
答案3
grep
有一个--fixed-strings
选项可以做你想做的事,你可以将它与以下选项一起使用find
:
find $musicroot -type f | grep --fixed-strings "R. Kelly - Step In The Name Of Love [mp3clan.com].mp3"
答案4
也许用这个命令来解析文件名tr
:
$ tr '[]' '*' <<< "$var"
R. Kelly - Step In The Name Of Love *mp3clan.com*.mp3