2016-08-14 5 views
2

Использование ls -Q с --quoting-style=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)' yields 'ls: невозможно получить доступ к anb: нет такого файла или каталога', поэтому он не работает в оба конца. Это не работает без 'eval'. – choroba

+0

'c', скорее всего, будет вашим лучшим выбором ... также в любое время, когда вы eval ls, а затем ls в суб-оболочке, он получит странные результаты. –

ответ

2

coreutils 8.25 имеет новый стиль цитирования «shell-escape» и фактически позволяет ему по умолчанию разрешать вывод из ls всегда полезным и быть безопасно копировать и вставлять обратно в другие команды.

+0

Это то, что я получил из отчета об ошибке. К сожалению, я все еще на 8.22 и 8.23 ​​на моих боксах. – choroba

0

Может быть не совсем то, что вы ищете, но стиль «побег», кажется, хорошо работать с предстоящим расширением ${[email protected]} параметра в bash 4.4.

$ 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) работал по назначению с обеими версиями.)