我使用脚本将下载的一些文件链接到不同的目录。当文件名中有“-”时, ln -s 将无法正确读取路径,即使该变量将正确记录到我使用的日志文件中。
for f in ${AVIFILES}
do
BaseAviName=$(basename "$f" .avi)
aviMp4name="'""$targetdir""/""$BaseAviName"".mp4""'"
linkAviFile="'""$targetdir""/""$f""'"
downloadedFile=$("'""$theFile""/""$f""'")
ln -s "$downloadedFile" "$linkAviFile" >>$logPath 2>&1
echo "fileIs: " "$f" ",linkAviFile is" "$linkAviFile" ",BaseAviName:" "$BaseAviName" '$aviMp4name: ' "$aviMp4name" '$downloadedFile: ' "$downloadedFile" >> "$logPath"
done
这是来自的错误消息ln
:
ln: failed to create symbolic link ‘'/home/user/Videos/TVEpisodes/Parks and Recreation/Parks.and.Recreation.S03E01.DVDRip.XviD-REWARD.avi'’ -> ‘’: No such file or directory
即使变量 downloadFile 使用正确的路径记录:
'/home/user/Downloads/Parks And Recreation - Season 3 - DVDRip-REWARD/Parks.and.Recreation.S03E01.DVDRip.XviD-REWARD.avi'
看来,出于某种原因,当 $downloadedFile 扩展为 ln 来使用它时,ln 将省略部分文件名,从第一个“-”到下一个“/”( - 第 3 季 - DVDRip-REWARD ) )。我找不到发生这种情况的充分理由,并且想避免它,有什么建议吗?
编辑:我重写了脚本,问题就消失了。感谢任何提供帮助的人
答案1
即使变量 downloadFile 使用正确的路径记录:
'/home/user/Downloads/Parks And Recreation - Season 3 - DVDRip-REWARD/Parks.and.Recreation.S03E01.DVDRip.XviD-REWARD.avi'
这显然不是正确的路径:它'
在开头和结尾都有额外的字符。您可以在以下错误消息中看到ln
:
ln: failed to create symbolic link ‘'/home/user/Videos/TVEpisodes/Parks and Recreation/Parks.and.Recreation.S03E01.DVDRip.XviD-REWARD.avi'’ -> ‘’: No such file or directory
'
错误消息的文件名位于“单引号”内,并且在开头和结尾处有额外的(ASCII 单引号)字符。
您的脚本中的问题很明显:您'
在定义aviMp4name
,linkAviFile
和时添加了额外的字符downloadedFile
。不要那样做。
for f in "${AVIFILES[@]}"
do
BaseAviName=$(basename -- "$f" .avi)
aviMp4name="$targetdir/$BaseAviName.mp4"
linkAviFile="$targetdir/$f"
downloadedFile=$("$theFile/$f")
ln -s -- "$downloadedFile" "$linkAviFile" >>$logPath 2>&1
echo "fileIs: " "$f" ",linkAviFile is" "$linkAviFile" ",BaseAviName:" "$BaseAviName" '$aviMp4name: ' "$aviMp4name" '$downloadedFile: ' "$downloadedFile" >> "$logPath"
done
在壳里源语法,单引号分隔文字字符串,例如a='hello world!'
将变量设置a
为 12 个字符的字符串hello world!
。如果你加上单引号到一个变量中,您将得到单引号:a="'hello world!'"
设置a
为 14 个字符的字符串'hello world!'
。
在 shell 脚本中使用引号时要记住的关键是在变量扩展两边加上双引号,例如ln -s -- "$downloadedFile" "$linkAviFile"
.像这样的代码ln -s -- $downloadedFile $linkAviFile
会分割变量的值downloadedFile
和linkAviFile
空白字符,并将每个部分解释为通配符模式。这些双引号是 shell 源语法的一部分,它们由解析器解释。将引号放入变量的值中不会解决任何问题。
另请注意,如果文件名以 开头-
,则命令会将其解释为选项。为了避免这种情况,当变量中有文件名时,请在所有选项之后和所有文件名之前将参数传递给命令(如果您确定文件名不以 开头,例如,如果您知道它们,则--
可以省略是绝对路径)。意思是“此后没有更多选择”。--
-
--
请注意${AVIFILES}
,与任何其他未加引号的扩展一样,它会在空格处拆分变量的值。要将多个文件名存储在一个变量中,请将其设为数组而不是字符串;这需要 ksh、bash 或 zsh,它在普通 sh 中不起作用:
AVIFILES=(foo.avi bar.avi "file name with spaces.avi")