当文件名作为变量传递时,ln -s 删除文件名的一部分

当文件名作为变量传递时,ln -s 删除文件名的一部分

我使用脚本将下载的一些文件链接到不同的目录。当文件名中有“-”时, 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会分割变量的值downloadedFilelinkAviFile空白字符,并将每个部分解释为通配符模式。这些双引号是 shell 源语法的一部分,它们由解析器解释。将引号放入变量的值中不会解决任何问题。

另请注意,如果文件名以 开头-,则命令会将其解释为选项。为了避免这种情况,当变量中有文件名时,请在所有选项之后和所有文件名之前将参数传递给命令(如果您确定文件名不以 开头,例如,如果您知道它们,则--可以省略是绝对路径)。意思是“此后没有更多选择”。-----

请注意${AVIFILES},与任何其他未加引号的扩展一样,它会在空格处拆分变量的值。要将多个文件名存储在一个变量中,请将其设为数组而不是字符串;这需要 ksh、bash 或 zsh,它在普通 sh 中不起作用:

AVIFILES=(foo.avi bar.avi "file name with spaces.avi")

相关内容