Как выбрать поле / столбец из вывода `ls -l`?

22

Моя цель обманчиво проста (по крайней мере, для меня). Я хочу взять вывод ls -lили ls -lhи выбрать только одно поле.

Я ищу, чтобы это было как можно более пуленепробиваемым, и я имею в виду, что имена файлов могут иметь переменное количество пробелов, не все в поле имеют одинаковую длину и т. Д.

Бонусные баллы за наличие скрипта, который будет принимать имя поля (или даже просто номер поля), а затем возвращать содержимое поля.

Я хочу включить

введите описание изображения здесь

в:

введите описание изображения здесь

soandos
источник

Ответы:

41

Попробуй ls -l | awk '{print $7}'.

awk выбирает столбцы, так что это идеально подходит для этой задачи.

Кори Уитакер
источник
3
Как объясняет @ormaaj: не полагайтесь на фрагменты информации, доступные в определенных местах с помощью ls. Команда findчрезвычайно полезна.
Пэдди Ландау
@PaddyLandau Как использовать команду find, чтобы напечатать размер файла в мегабайтах, как я могу с ls -l --block-size=M?
SurpriseDog
@Benjamin - lsкоманда не является стандартом POSIX, поэтому сценарий, который зависит от него, lsможет сломаться в разных системах или даже со временем. Смотрите ответ @ormaaj на этой странице для более подробной информации. Один из способов сделать то, что вы просите, - использовать цикл Bash. Вот пример. for FILENAME in *; do FILESIZE=$(( $( stat --format=%s "${FILENAME}" ) / 1024 )); echo "${FILENAME}" ${FILESIZE}; done, Конечно, вместо того echo, чтобы использовать вашу обработку.
Пэдди Ландау
@PaddyLandau Я только что закончил вывод результатов команды find, ... | xargs -d '\n' du -mкоторая работает так же хорошо.
SurpriseDog
@ Бенджамин Вы можете посмотреть на -execвариант find.
Пэдди Ландау
17

Никогда не разбирай ls . Используйте GNU find. Или , если портативность не важно, stat(1).

find . -maxdepth 1 -printf '%Td\n'

Для чтения данных, кроме списков имен файлов, построчно и разделения на поля, см .: BashFAQ / 001

Нет способов надежно прочитать список имен файлов, разделенных новой строкой, которые имеют смысл в большинстве случаев.

ormaaj
источник
1

Вы можете получить конкретный столбец в оболочке, например:

ls -al | while read perm bsize user group size month day time file; do echo $day; done

или , awkкак показано на @Corey ответ , cut -c44-45также будет работать после настройки (с lsзакрепил столбцы), или что - то еще, однако основная проблема заключается в том , что он не будет надежным и пуленепробиваемые (например , на Unix может быть $6, не $7, и это изменяется в зависимости от аргументов), что делает его не дружественным к машине, поэтому вообще не рекомендуется разбирать lsкоманду .

Лучше всего использовать различные доступные команды, такие как findили stat, которые могут предоставить соответствующие опции для форматирования вывода, как вам нужно. Например:

$ stat -c "%x %n" *
2016-04-10 04:53:07.000000000 +0100 001.txt
2016-04-10 05:08:42.000000000 +0100 7c1c.txt

Чтобы вернуть столбец только дней изменений, попробуйте этот пример:

stat -c "%x" * | while read ymd; do date --date="$ymd" "+%d"; done

Стоит отметить, что GNU statможет иметь разные параметры по сравнению с BSD stat, поэтому он не будет пуленепробиваемым в разных операционных системах.

kenorb
источник
1
+1 за упоминание, что ls не должен анализироваться так же как и для использования stat. dateоднако настроен неправильно. Нужно добавить --date=$ymd, так dateкак сам по себе напечатает текущий день, но цель здесь - преобразовать формат даты файла
Сергей Колодяжный
ls -la | cut -c32-33Команда в полной честности просто совершенно ненадежна, а не только из - за возможные ошибки , с именами файлов, но просто потому , что это зависит от длины и от файлов имен пользователей и размера. Команда stat -c "%x" *.*выглядит хорошо, но, используя *.*ее, вы ограничиваете ее только именами файлов, содержащими точку. Я предполагаю, что намерение было поймать также скрытые файлы; в этом случае вы должны включить подстановку для заранее и составляют скрытые использовать *вместо *.*: shopt -s dotglob; stat -c "%x" * | [...].
Кос
А также, что сказал и Сергей, вы должны добавить --date="$ymd"в dateкоманду, иначе она напечатает текущий день месяца.
Кос
Спасибо за комментарии. Я рассмотрел проблемы и представил лучший начальный пример.
Кенорб