2016-08-14 13 views
2

で正しく引用されていませんls -Q--quoting-style=shellを使用すると、ファイル名の改行(yes、I know ...)が?に変わります。これはバグですか?ファイル名をシェル(100%互換)の形式で取得する方法はありますか(可能であればshまたはbash)。改行がls-Q

例(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

'--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には新しい 'シェルエスケープ'クォートスタイルがあり、実際にはlsの出力を常に使用可能にし、コピーして他のコマンドに貼り付けても安全です。

+0

これは私がバグレポートから得たものです。残念ながら、私はまだ私のボックスで8.22と8.23です。 – choroba

0

はそうでないかもしれない、非常にあなたが探しているが、「エスケープ」スタイルbash 4.4で開催${[email protected]}パラメータ展開でうまく動作するようです。 --quoting-style=escape$'...'に包まれているとの互換性があるように、それはで、見える、実験のビットから

${[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

私は1つを見つけることができません。マニュアルページの関連部分をコピーします。 – chepner

0

:ここ

$ 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の関連する部分であります2つの例外:

  • バックスラッシュを付加することでスペースを逃します。 $'...'はスペースの前にバックスラッシュを破棄しません。
  • シングルクォートをエスケープしません。

だからあなたはおそらく(バッシュで)このような何かを書くことができ:

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 %q続くエスケープを処理するためにprintfを使用したバージョンです:

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 
} 

はそれが最初のバージョン、一部のケースがあることが判明した場合が正しく処理されない場合は、2番目のバージョンで同じ問題が発生する可能性が高くなります。 (FWIW、eval ls -l $(ls-quote-shell)は両方のバージョンで意図したとおりに動作しました)