2016-08-14 61 views
2

中没有正确引用的换行符使用ls -Q--quoting-style=shell,文件名中的换行符(是的,我知道...)变成?。这是一个错误?有没有办法如何获得与shell 100%兼容的格式的文件名(如果可能,sh或bash)?在ls -Q

例(庆典):

$ 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

'--quoting-style =“escape”'或'--quoting-style =“c”'应该可以工作...... –

+0

@ l'L'l:不。 'eval ls $(ls -Q --quoting-style = escape)'产生'ls:不能访问anb:没有这样的文件或目录',所以它不会往返。如果没有'eval',它也不起作用。 – choroba

+0

'c'可能是你最好的选择......任何时候你都可以在一个子壳中评估它会得到奇怪的结果。 –

回答

2

coreutils 8.25具有新的'shell-escape'引用样式,实际上默认情况下它允许ls的输出始终可用,并且是安全地复制并粘贴回其他命令。

+0

这也是我从错误报告中得到的。不幸的是,我的盒子上仍然是8.22和8.23。 – choroba

0

也许不太你在找什么,但“越狱”风格似乎与bash 4.4即将到来的${[email protected]}参数扩展很好地工作。

$ touch $'a\nb' $'c\nd' 
$ ls -Q --quoting-style=escape ??? | while IFS= read -r fname; do echo =="${[email protected]}==="; done 
==a 
b== 
==c 
d== 

这里是man page的相关部分(链接到原始源):

${[email protected]} 
      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. 
+0

我找不到解释,你有链接吗? – choroba

+1

我找不到一个;我将复制手册页的相关部分。 – chepner

0

从实验位,它看起来像--quoting-style=escape是与被包裹在$'...'兼容,具有两个例外:

  • 它通过预置一个反斜杠来转义空格;但$'...'不会在空格前放弃反斜杠。
  • 它不会脱离单引号。

所以,你也许可以写这样的事情(Bash中):

function ls-quote-shell() { 
    ls -Q --quoting-style=escape "[email protected]" \ 
    | 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重新逃生的壳友好的方式的一个版本:

function ls-quote-shell() { 
    ls -Q --quoting-style=escape "[email protected]" \ 
    | 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)按照既定版本的预期工作)。