I'm running Git Bash on Windows, and I'm attempting to write a wrapper function for ls
which handles Windows' hidden file flags correctly.
The command cmd.exe /c "dir /b /a/h"
will output a list of files in a directory which have a hidden flag. Each filename is output on one line, separated by \r\n
(being Windows). Filenames with spaces are surrounded with single quotes.
$ cmd.exe /c "/b /ah"
.gitconfig
desktop.ini
'hidden file.txt'
I then want to format this as a list of --ignore
options for the final ls
call.
--ignore='.gitconfig' --ignore='desktop.ini' --ignore='hidden file.txt'
I'm using a for
loop, after setting IFS='\r\n'
, which should allow me to format each filename string with --ignore='
and '
.
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 "$@"
}
However, the string isn't being split, and all instances of n
and r
in the output are being replaced with a space, so the resulting string is garbled.
$ ls
--ig o e='.gitco fig
desktop.i i
hidde file.txt'
What am I doing wrong?
Collecting options into a single string variable is going to end up badly. Use an array instead.
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[@]}"
}
See also http://mywiki.wooledge.org/BashFAQ/050 for an extended discussion.