繁体   English   中英

Bash和变量替换名称中带有空格的文件:gpsbabel的申请

[英]Bash and Variable Substitution for file with space in their name: application for gpsbabel

我正在尝试编写脚本以运行gpsbabel。 我陷于处理名称包含(空格)的文件。 我的问题是在bash语法中。 bash程序员的任何帮助或见解将不胜感激。

gpsbabel是允许合并gps设备记录的曲目的软件。
对于我而言,可以正常工作的语法是:

gpsbabel -i gpx -f "file 1.gpx" -f "file 2.gpx" -o gpx -F output.gpx -x track,merge

GPS数据的输入格式由-i给出,输出格式由-o给出 输入数据文件在-f之后列出,结果文件在-F之后

(请参阅gpsbabel手册 ,请参见示例4.9)

我正在尝试编写一批批处理,以使用最初不知道的许多输入文件来运行此语法。 这意味着必须对从批处理参数传递的每个输入文件重复序列-f“ name_of_the_input_file”

这是一个脚本,用于文件名中没有空格的文件

#!/bin/bash
# Append multiple gpx files easily
# batch name merge_gpx.sh
# Usage:
# merge_gpx.sh track_*.gpx

gpsbabel -i gpx $(echo $* | for GPX; do echo -n " -f $GPX "; done) \
-o gpx -F appended.gpx

`因此,我试图修改此脚本以处理包含空格的文件名。 我迷上了bash替代,写了更多的bash用于调试目的,但没有成功。

这是我的审判之一
我从gpsbabel “命令行上的额外参数”收到错误消息,提示我在变量用法上犯了一个错误。

    #/bin/bash
    # Merging all tracks in a single one

    old_IFS=$IFS     # Backup internal separator  
    IFS=$'\n'        # New IFS

    let i=0
    echo "  Merging GPX files"

    for file in $(ls -1  "$@")
    do
        let i++
        echo "i=" $i ","  "$file" 
        tGPX[$i]=$file
    done
    IFS=$old_IFS     #           
    #
    echo "Number of files:" ${#tGPX[@]}
    echo 
    # List of the datafile to treat (each name protected with a ')
    LISTE=$(for (( ifile=1; ifile<=${#tGPX[@]} ; ifile++)) ;do echo -ne " -f '""${tGPX[$ifile]}""'"; done)

    echo "LISTE: " $(echo -n $LISTE) 

    echo "++Merging .."
    if (( $i>=1 )); then
              gpsbabel -t \
                     -i gpx  $(echo -n $LISTE)  \
                     -x track,merge,title="TEST COMPIL" \
                     -o gpx -F track_compil.gpx
      else
            echo "Wrong selection of input file"
    fi

    #end

使用数组:

files=()
for f; do
    files+=(-f "$f")
done
gpsbabel -i gpx "${files[@]}" -o gpx -F appended.gpx

for f; do for f; dofor f in "$@"; do缩写for f in "$@"; do for f in "$@"; do ; 大多数情况下,您想使用$@而不是$*来访问命令行参数。 引用"${files[@]}"会产生一个单词列表,每个元素一个,就好像被引用一样,因此将包含空格的数组元素视为一个单词。

您使自己的事情变得复杂得多。

任何合理的posix / gnu兼容实用程序,它采用两个命令行参数( -f STRING或等效的-f FILENAME )形式的选项,也应接受单个命令行参数-fSTRING 如果该实用程序使用getoptgetopt_long ,则这是自动的。 gpsbabel似乎没有使用标准的posix或gnu库进行参数解析,但我相信它仍然可以解决这个问题。

显然,您的脚本希望其参数为文件名列表; 大概,如果文件名包含空格,您将引用包含空格的名称:

./myscript "file 1.gpx" "file 2.gpx"

在这种情况下,您只需要在参数列表前加上-f即可更改参数列表,从而使参数列表生效:

"-ffile 1.gpx" "-ffile 2.gpx"

这非常简单。 我们将使用bash手册中介绍的bash特定的查找和替换语法:(我着重介绍了此解决方案使用的两个功能)

${parameter/pattern/string}

模式替换。 与路径名扩展一样,扩展模式以产生模式。 扩展参数,并将模式与其值的最长匹配项替换为字符串。 如果pattern以/开头,则pattern的所有匹配项都将替换为字符串。 通常只替换第一个比赛。 如果pattern以开头,则它必须与参数的扩展值的开头匹配。 如果pattern以开头,则它必须在参数的扩展值的末尾匹配。 如果string为null,则删除模式匹配项,并且/后面的模式可以省略。 如果parameter为@* ,则将替换操作依次应用于每个位置参数,并且扩展为结果列表。 如果parameter是用@*下标的数组变量,则将替换操作依次应用于数组的每个成员,并且扩展为结果列表。

因此, "${@/#/-f}"是参数列表( @ ),在开头( )处的空模式被-f替换:

#/bin/bash
# Merging all tracks in a single one

# $# is the number of arguments to the script.
if (( $# > 0 )); then
        gpsbabel -t \
                 -i gpx  "${@/#/-f}" \
                 -x track,merge,title="TEST COMPIL" \
                 -o gpx -F track_compil.gpx
  else
        # I changed the error message to make it more clear, sent it to stderr
        # and cause the script to fail.
        echo "No input files specified" >> /dev/stderr
        exit 1
fi

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM