将ls -Q
与--quoting-style=shell
一起使用,文件名中的换行符(是的,我知道......)将变为?
。这是一个错误吗?有没有办法如何以与shell(如果可能的话,sh或bash)100%兼容的格式获取文件名?
示例(bash):
$ touch a$'\n'b
$ for s in literal shell shell-always c c-maybe escape locale clocale ; do
ls -Q a?b --quoting-style=$s
done
a?b
'a?b'
'a?b'
"a\nb"
"a\nb"
a\nb
‘a\nb’
‘a\nb’
答案 0 :(得分:2)
coreutils 8.25拥有全新的shell-escape'引用样式,实际上默认情况下允许ls的输出始终可用,并且可以安全地复制并粘贴回其他命令。
答案 1 :(得分:0)
也许不是你想要的,但“逃避”风格似乎适用于${...@E}
4.4中即将进行的bash
参数扩展。
$ touch $'a\nb' $'c\nd'
$ ls -Q --quoting-style=escape ??? | while IFS= read -r fname; do echo =="${fname@E}==="; done
==a
b==
==c
d==
以下是man page的相关部分(链接到原始来源):
${parameter@operator}
Parameter transformation. The expansion is either a transforma-
tion of the value of parameter or information about parameter
itself, depending on the value of operator. Each operator is a
single letter:
Q The expansion is a string that is the value of parameter
quoted in a format that can be reused as input.
E The expansion is a string that is the value of parameter
with backslash escape sequences expanded as with the
$'...' quoting mechansim.
P The expansion is a string that is the result of expanding
the value of parameter as if it were a prompt string (see
PROMPTING below).
A The expansion is a string in the form of an assignment
statement or declare command that, if evaluated, will
recreate parameter with its attributes and value.
a The expansion is a string consisting of flag values rep-
resenting parameter's attributes.
If parameter is @ or *, the operation is applied to each posi-
tional parameter in turn, and the expansion is the resultant
list. If parameter is an array variable subscripted with @ or
*, the case modification operation is applied to each member of
the array in turn, and the expansion is the resultant list.
The result of the expansion is subject to word splitting and
pathname expansion as described below.
答案 2 :(得分:0)
通过一些实验,看起来--quoting-style=escape
与$'...'
中包含的内容兼容,但有两个例外:
$'...'
不会在空格之前丢弃反斜杠。所以你也许可以写这样的东西(在Bash中):
function ls-quote-shell () {
ls -Q --quoting-style=escape "$@" \
| while IFS= read -r filename ; do
filename="${filename//'\ '/ }" # unescape spaces
filename="${filename//"'"/\'}" # escape single-quotes
printf "$'%s'\n" "$filename"
done
}
为了测试这个,我创建了一个目录,其中包含一堆带有奇怪字符的文件名;和
eval ls -l $(ls-quote-shell)
按预期工作。 。 。虽然我不会对此作出任何确定的保证。
或者,这是一个使用printf
来处理转义的版本,然后printf %q
以shell友好的方式重新转义:
function ls-quote-shell () {
ls -Q --quoting-style=escape "$@" \
| while IFS= read -r escaped_filename ; do
escaped_filename="${escaped_filename//'\ '/ }" # unescape spaces
escaped_filename="${escaped_filename//'%'/%%}" # escape percent signs
# note: need to save in variable, rather than using command
# substitution, because command substitution strips trailing newlines:
printf -v filename "$escaped_filename"
printf '%q\n' "$filename"
done
}
但如果事实证明某些情况下第一个版本无法正确处理,那么第二个版本很可能会遇到同样的问题。 (FWIW,eval ls -l $(ls-quote-shell)
按两种版本的预期工作。)