使用 bash 处理文件链接中的空间

Pat*_*vák 5 bash scripts

我有问题。这是我的 bash 脚本,用于将视频与 subs 合并:

#!/bin/bash 

cd /media/ptrknvk/'TOSHIBA EXT'/Shows/My/'Doctor Who'/

url0='DW s11e0'
url1='DW\ s11e'

for(( i=1; i<11; i++ ))
do
    if ! [ $i -gt 9 ]; 
    then
        mkvmerge -o $url0$i.mkv $url0$i.mkv $url0$i.srt
        rm $url0$i.srt
    else
        mkvmerge -o $url1$i.mkv $url1$i.mkv $url1$i.srt
        rm $url1$i.srt
    fi
done
Run Code Online (Sandbox Code Playgroud)

文件的名称类似于“DW s11e05.mkv”,它们实际上存在于目录中。

这是一个结果:

mkvmerge v8.8.0 ('Wind at my back') 64bit
Error: The file 's11e09.mkv' could not be opened for reading: open file error.
rm: cannot remove 'DW': No such file or directory
rm: cannot remove 's11e09.srt': No such file or directory
mkvmerge v8.8.0 ('Wind at my back') 64bit
Error: The file 's11e10.mkv' could not be opened for reading: open file error.
rm: cannot remove 'DW\': No such file or directory
rm: cannot remove 's11e10.srt': No such file or directory
Run Code Online (Sandbox Code Playgroud)

如您所见,此处的空格不起作用之前的 '\'。我也尝试使用 echo,但没有任何改变(我以错误的方式使用它)。

对不起,我有点笨拙的风格。

ter*_*don 11

你需要引用你的变量。这应该做你想做的:

#!/bin/bash 

cd /media/ptrknvk/'TOSHIBA EXT'/Shows/My/'Doctor Who'/

url0='DW s11e0'
url1='DW s11e'

for(( i=1; i<11; i++ ))
do
    if ! [ $i -gt 9 ]; 
    then
        mkvmerge -o "$url0$i.mkv" "$url0$i.mkv" "$url0$i.srt" &&
        rm "$url0$i.srt"
    else
        mkvmerge -o "$url1$i.mkv" "$url1$i.mkv" "$url1$i.srt" &&
        rm "$url1$i.srt"
    fi
done
Run Code Online (Sandbox Code Playgroud)

请注意,我还在&&每个mkvmerge命令之后添加了一个,因此rm只有mkvmerge在成功时才运行。如果合并失败,您不想删除字幕文件!

也就是说,虽然你的方法绝对没有错,但我觉得你可以使用 shell globbing 使它变得相当简单和优雅:

#!/bin/bash 

for file in "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/"DW*mkv; do
  srtFile=${file//.mkv/.srt}
  mkvmerge -o "$file" "$file" "$srtFile" && rm "$srtFile"
done
Run Code Online (Sandbox Code Playgroud)

您甚至不需要为此编写脚本。您可以直接在终端中将它作为单行运行:

for file in "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/"DW*mkv; do
  mkvmerge -o "$file" "$file" "${file//.mkv/.srt}" && rm "${file//.mkv/.srt}";
done
Run Code Online (Sandbox Code Playgroud)


wja*_*rea 6

引用变量以防止分词。顺便说一句,整个字符串上的双引号是首选样式。

#!/bin/bash

# Also exit if this fails
cd "/media/ptrknvk/TOSHIBA EXT/Shows/My/Doctor Who/" || exit

url0="DW s11e0"
url1="DW s11e"

for (( i=1; i<11; i++ )); do
    # Also why use "not greater-than" when "less-than-or-equal" exists?
    if [ $i -le 9 ]; then
        # Also you can DRY* out this part with variables.
        url="$url0"
    else
        url="$url1"
    fi
    # Also when concatenating variables, it's clearer to use the "${var}" style. **
    f_mkv="${url}${i}.mkv"
    f_srt="${url}${i}.srt"
    mkvmerge -o "$f_mkv" "$f_mkv" "$f_srt"
    rm "$f_srt"
done
Run Code Online (Sandbox Code Playgroud)

Shellcheck对于在 shell 脚本中查找此类问题非常有用。

* DRY =不要重复自己

** 或者你可以使用printf -v,但在这种情况下它不是一个很大的改进。例如

printf -v f_mkv "%s%s.mkv" "$url" $i
Run Code Online (Sandbox Code Playgroud)