2016-08-14 58 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)按照既定版本的預期工作)。