我正在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 "$@"
}
但是,字符串没有被拆分,输出中的所有n
和r
实例都被替换为空格,因此生成的字符串会出现乱码。
$ ls
--ig o e='.gitco fig
desktop.i i
hidde file.txt'
我究竟做错了什么?
将选项收集到单个字符串变量中将会很糟糕。请改用数组。
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[@]}"
}
你是echo
ing options
中没有引用的文件名,echo
将它们视为单独的参数来回应:
echo "$options"
应该工作正常。
最后我按照@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
按预期工作。