如何将字符串列表格式化为Bash函数中的一组命令选项/参数对

问题描述 投票:1回答:3

我想做的事

我正在Windows上运行Git Bash,我正在尝试为ls编写一个包装函数,它正确处理Windows的隐藏文件标记。

命令cmd.exe /c "dir /b /a/h"将输出目录中具有隐藏标志的文件列表。每个文件名在一行上输出,由\r\n(Windows)分隔。带空格的文件名用单引号括起来。

$ cmd.exe /c "/b /ah"
.gitconfig
desktop.ini
'hidden file.txt' 

然后我想将其格式化为最终--ignore调用的ls选项列表。

--ignore='.gitconfig' --ignore='desktop.ini' --ignore='hidden file.txt'

我试过的

在设置for之后,我正在使用IFS='\r\n'循环,这应该允许我使用--ignore=''格式化每个文件名字符串。

function ls {
    options=""
    IFS="\r\n"
    for filename in $(cmd.exe /c "dir /b /ah")
        do options="${options}--ignore='$filename' "
    done

    echo $options
    # command ls $options "$@"
}

但是,字符串没有被拆分,输出中的所有nr实例都被替换为空格,因此生成的字符串会出现乱码。

$ ls
--ig o e='.gitco fig
desktop.i i
hidde  file.txt'

我究竟做错了什么?

string windows bash function ls
3个回答
2
投票

将选项收集到单个字符串变量中将会很糟糕。请改用数组。

ls () {
    options=()
    local IFS="\r\n"
    while read -r filename; do
        case $filename in \'*\')
            filename=${filename#\'}; filename=${filename%\'};;
        esac
        options+=("--ignore=$filename")
    done < <(cmd.exe /c "dir /b /ah")

    # echo will flatten the arguments, maybe just run git here
    echo "${options[@]}"
}

另见http://mywiki.wooledge.org/BashFAQ/050进行扩展讨论。


0
投票

你是echoing options中没有引用的文件名,echo将它们视为单独的参数来回应:

echo "$options"

应该工作正常。


0
投票

最后我按照@tripleee的推荐使用了一个数组,但是使用了一个简单的for循环而不是while read。不需要显式处理多字文件名周围的引号。

function ls {
    local IFS=$'\r\n'
    options=()
    for filename in $(cmd.exe /c "dir /b /ah 2> null")
        do options+=("--hide=$filename")
    done

    command ls "${options[@]}" "$@"
}

使用--hide选项而不是--ignore允许-a--all按预期工作。

© www.soinside.com 2019 - 2024. All rights reserved.