我有以下代码用他们的艺术家标记我的FLAC文件:
#!/bin/bash
# This script gets called with a directory of flac-audio-files to tag
#
# The files MUST have a filename of format "Artist - Title.flac"
# The whitespaces in the filename-format are optional
for file in $1/*; do
name=$(echo "$file" | cut -d'/' -f 2) # removes leading slashes and dirnames
artist=$(echo "$name"| cut -d'-' -f 1) # cuts the artists name out of the name
artist=$(echo "$artist" | awk '{$1=$1};1') # removes Whitespaces before and after
fname=$(echo "$file" | awk '{gsub(/ /,"\\ ");print}') # Supposed to escape spaces
fname=$(echo "$file" | awk '{gsub(/\(/,"\\(");print}') # Supposed to escape (
fname=$(echo "$file" | awk '{gsub(/)/,"\\)");print}') # Supposed to escape )
echo "metaflac --set-tag=\"ARTIST=$artist\" $fname"
metaflac --set-tag=\"ARTIST=$artist\" "$fname" # Tags the Song, finally
done
这将输出命令(带有回显“ metaflac ...”部分),这些命令在通过复制和粘贴执行时可以完美执行,但是回显之后的命令将输出“找不到文件”错误。我想念什么?
编辑: 引用文件名也会导致找不到文件的错误,然后执行单词拼写。
ls "some file with spaces"
"some : File not found!
file : File not found!
with : File not found!
spaces" : File not found!
答案 0 :(得分:1)
乍一看,我认为您的问题是实际命令中引号的不必要转义,例如--set-tag=\"ARTIST=$artist\"
。但是,您得到的错误是该文件不存在。
这是因为您正在修改文件名,然后只是希望该文件存在。但是您实际上尚未重命名该文件。你所做的一切修改的变量fname
,其中包含实际文件名,存储在的修改版本file
。
不清楚在$fname
中转义空格和括号的意图是什么,但是无论如何,该文件实际上都不存在。
我怀疑您正在尝试转义括号和空格,以便外壳程序不会抱怨,就像您在命令行中直接输入文件名时的处理方式,例如:
ls some\ file\ \(with\ spaces\ and\ parentheses\).txt
但是,在脚本中,您无需经历所有麻烦。您只需要确保在命令中使用$file
即可引用>
metaflac --set-tag="ARTIST=$artist" "$file"
当在文件名两边加上引号时,shell不会尝试对文件名进行单词拆分。此外,企图逃跑的事情像你这样做实际上不会反正工作,因为扩大后壳不会承认你的转义$fname
。而是将它们视为只是文字\
字符。
例如:
> touch "some file"
> ls -l
-rw-r--r-- 1 user user 0 2019.02.01 12:11 some file
> var="some\ file"
> ls "$var"
ls: cannot access 'some\ file': No such file or directory
即使您删除了$var
周围的引号,它仍然无效:
> ls $var
ls: cannot access 'some\': No such file or directory
ls: cannot access 'file': No such file or directory
删除引号引起壳里做的扩展型变量字拆分,但它仍然认为反斜杠作为文字字符,而不是逃避。您可以使用eval
使它正常工作(但这仍然不是正确的方法):
> eval "ls -l $var"
-rw-r--r-- 1 user user 0 2019.02.01 12:11 some file
正确的方法是只确保正确引用变量,而不要尝试转义:
> var="some file" # No need to escape the space
> ls -l "$var" # Quotes around $var
-rw-r--r-- 1 user user 0 2019.02.01 12:11 some file
您也可以直接在命令行上使用引号,以避免不得不转义:
> ls this\ is\ the\ hard\ way.txt
this is the hard way.txt
> ls "this is the easy way.txt"
this is the easy way.txt