linux - Bash 和变量替换名称中带有空格的文件 : application for gpsbabel

标签 linux bash gps whitespace space

我正在尝试编写一个脚本来运行 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 manual,参见示例 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 "Extra arguments on command line" 得到一个错误提示我在变量使用上犯了一个错误。

    #/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

最佳答案

你让事情变得比他们需要的更复杂。

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

显然,您的脚本希望它的参数是一个文件名列表;据推测,如果文件名包含空格,您将引用包含空格的名称:

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

在那种情况下,您只需要通过在每个参数前添加 -f 来更改参数列表,这样参数列表实际上就变成了:

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

这非常简单。我们将使用特定于 bash 的查找和替换语法,如 bash manual 中所述。 :(我强调了此解决方案使用的两个功能)

${parameter/pattern/string}

Pattern substitution. The pattern is expanded to produce a pattern just as in pathname expansion. Parameter is expanded and the longest match of pattern against its value is replaced with string. If pattern begins with /, all matches of pattern are replaced with string. Normally only the first match is replaced. If pattern begins with #, it must match at the beginning of the expanded value of parameter. If pattern begins with %, it must match at the end of the expanded value of parameter. If string is null, matches of pattern are deleted and the / following pattern may be omitted. If parameter is @ or *, the substitution operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the substitution operation is applied to each member of the array in turn, and the expansion is the resultant list.

因此,"${@/#/-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

关于linux - Bash 和变量替换名称中带有空格的文件 : application for gpsbabel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25344664/

相关文章:

带有where选项的java mysqldump

linux - X11 图形用户界面性能

linux - 如何在 shell 脚本中将每日磁盘使用情况导出为 csv 格式?

php - 调用某些运行 bash 脚本的 php 脚本函数

java 如何在世界地图上使用经度和纬度标记地点

c++ - 一个简单的 pthread_create 在 Qt 中导致 100% 的 CPU 使用率

arrays - BASH:如何创建安装脚本以构建另一个脚本

linux - shell 脚本 - 需要根据上面的输出将邮件发送到特定的 id

python - pyserial - 如果串行设备断开连接,我想收到错误消息

iOS map GPS 位置在 map 上实现蓝球定位和箭头标志