Подтвердить что ты не робот

Awk '{print $9}' последний столбец ls -l, включая любые пробелы в имени файла

Как получить awk для вывода полного имени файла в ls -l если в некоторых файлах есть пробелы. Обычно я могу запустить эту команду:

ls -l | awk '{print $9}'

Это не работает, если в файлах есть пробелы. Можно ли как-то напечатать 9, 10, 11 и т.д.?

4b9b3361

Ответ 1

Лучшее решение: не пытайтесь сначала проанализировать вывод ls.

В официальной вики канала irc.freenode.org # bash есть объяснение, почему это плохая идея, и какие альтернативные подходы вы можете использовать вместо этого: http://mywiki.wooledge.org/ParsingLs

Использование find, stat и аналогичные инструменты обеспечат функциональность, которую вы ищете без подводные камни (не все из которых очевидны - некоторые из них возникают только при переходе на платформы с различными реализациями ls).

В вашем конкретном примере я предполагаю, что вы пытаетесь найти только файлы (а не каталоги) в вашем текущем каталоге; ваша текущая реализация с использованием ls -l является ошибкой, поскольку она исключает файлы с разрешениями + t или setuid. Правильный способ реализовать это будет следующим:

find . -maxdepth 1 -type f -printf '%f\n'

Ответ 2

Просто для завершения. Это также можно сделать с помощью sed:

# just an exercise in regex matching ...
ls -l | sed -E  -e '1d; s/^([^ ]+ +){8}//' 

Ответ 3

Там, вероятно, лучший подход, который предполагает как-то объединение полей, но:

$ echo 1 2 3 4 5 6 7 8 9 10 11 12 13 14... | 
  awk '{for (i = 9 ; i <= NF ; i++) printf "%s ", $i}'
9 10 11 12 13 14... 

Используя printf "%s " $i буду печатать i-ое поле с пробелом после него, а не перевод строки. Цикл for просто говорит, что нужно перейти от поля 9 к последнему полю.

Ответ 4

echo 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 | 
  awk 'BEGIN {OFS=ORS=""} ; {for (i=9;i<NF;i++) print $i " "; print $NF "\n"}'

Ответ 5

Если вы все еще настаиваете на ls -l вместо find или других инструментов, вот мое решение. Это не красиво и не разрушительно

  1. Уничтожьте $ 1.. $ 8, установив их в "" через цикл for
  2. Это оставляет кучу пробелов, предшествующих $ 9, удалите их с помощью команды sub()
  3. Распечатайте оставшиеся
ls -l | awk '{for (i = 1; i < 9; i++) $i = ""; sub(/^ */, ""); print}'

Ответ 6

Решение состоит в том, чтобы кодировать и декодировать пространство словом или символом, используя sed:

ls -l | sed s/\ /{space}/ | awk '{print $9}' | sed s/{space}/\ /

Это заменит все пробелы в строке на {space} перед передачей в awk. После того, как строка перешла на awk, мы заменяем {space} на пробел.

find как утверждают другие, является гораздо лучшим решением. Но если вам действительно нужно использовать awk, вы можете попробовать это.

Ответ 7

ls -l | awk -v x=9 '{print $x}'

Я использую это для получения имен каталогов без инцидентов. Я заметил, что решение find отлично подходит, если вы не уверены в типах файлов, если вы знаете, что смотрите на ls -l, работает отлично, по умолчанию в алфавитном порядке.

Ответ 8

Используя менее известную функцию AWK, можно установить ширину поля.

Однако в большинстве случаев, поскольку ls -l обычно использует динамическую ширину столбцов, это не будет хорошим решением. Но шириной столбцов также можно управлять, установив LS_COLWIDTHS.

Предположим, что ls -l возвращает:

▶ ls -l 
total 0
-rw-r--r--  1 alexharvey  wheel  0 12 Apr 20:48 file with spaces
-rw-r--r--  1 alexharvey  wheel  0 12 Apr 20:48 file1
-rw-r--r--  1 alexharvey  wheel  0 12 Apr 20:48 file2
lrwxr-xr-x  1 alexharvey  wheel  5 12 Apr 20:48 [email protected] -> file1

Предположим, я хочу обработать строку даты и имя файла как два отдельных поля:

▶ LS_COLWIDTHS="0:0:1:10:5:0:0:30" ls -l | 
   awk 'BEGIN {FIELDWIDTHS = "12 2 12 7 2 13 30"} NR > 1 {print $6, $7}'                                                       
12 Apr 20:48  file with spaces
12 Apr 20:48  file1
12 Apr 20:48  file2
12 Apr 20:48  [email protected] -> file1

Объяснение:

  • FIELDWIDTHS - это список значений ширины поля, разделенных FIELDWIDTHS. Когда установлено, AWK анализирует входные данные в поля фиксированной ширины вместо использования значения переменной FS в качестве разделителя полей.

  • NR > 1 использует специальную переменную NR которая по сути является номером строки. Я хочу, чтобы только строки с номерами больше 1 пропускали первую строку вывода ls.

  • К сожалению, LS_COLWIDTHS определяет столбцы в порядке, отличном от того, что они появляются в ls -l. Поэтому это запутанная функция для использования.

Смотрите также: