Awk '{print $9}' последний столбец ls -l, включая любые пробелы в имени файла
Как получить awk для вывода полного имени файла в ls -l
если в некоторых файлах есть пробелы. Обычно я могу запустить эту команду:
ls -l | awk '{print $9}'
Это не работает, если в файлах есть пробелы. Можно ли как-то напечатать 9, 10, 11 и т.д.?
Ответы
Ответ 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.. $ 8, установив их в "" через цикл for
- Это оставляет кучу пробелов, предшествующих $ 9, удалите их с помощью команды sub()
- Распечатайте оставшиеся
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
. Поэтому это запутанная функция для использования.
Смотрите также: