Как расширить команду ls с помощью настраиваемого столбца

Вопрос или проблема

Интересно, возможно ли изменить команду ls -l добавлением пользовательского столбца.

Например, я хотел бы, чтобы этот столбец содержал для каждого файла, скажем, первую строку $(CustomCommand FILE).

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

$ export CustomCommand=file
$ alias ls=/tmp/test/myls
$ ls
a  b  c  myls
$ ls -l
-rw-rw-r-- 1 steve steve   0 Sep 22 19:17 a a: пусто
-rw-rw-r-- 1 steve steve   0 Sep 22 19:17 b b: пусто
-rw-rw-r-- 1 steve steve   0 Sep 22 19:17 c c: пусто
-rwxr-xr-x 1 steve steve 127 Sep 22 19:18 myls myls: скрипт оболочки POSIX,   исполняемый текст ASCII

myls:

#!/bin/sh
if [ "$1" = "-l" ]
then
  shift
  ls -l $* | awk 'NF>2{ printf "%s ",$0 ; system("$CustomCommand " $NF) }'
else
  ls $*
fi

Вот подход, который объединяет paste, sed, ls и сохраняет его в bashrc. Он состоит из двух основных частей:

  • “custom_command”, которая принимает аргументы, но просто добавляет префикс “YYY” к каждому переданному аргументу и добавляет “ZZZ”. Фактическая команда CustomCommand, конечно, будет делать что-то другое.
  • псевдоним с именем “ls1”, который включает вызов custom_command. Назван “ls1”, чтобы избежать конфликта с “ls”, так как мы все еще полагаемся на “ls”.

Итак, в вашем ~/.bashrc добавьте:

custom_command ()
{
    for i; do
        echo "YYY${i}ZZZ"
    done
}

alias ls1='paste <( ls -lh | sed 1d ) <( custom_command * )'

А затем . ~/.bashrc, чтобы сделать это активным в текущем терминале.

Если в текущем каталоге находятся ‘dir1’, ‘file1’, ‘file2’ и ‘file 3’ (чтобы протестировать файл с пробелами), вы можете выполнить псевдоним ls1 и увидеть:

$ ls1
drwxr-xr-x 2 meme meme 4.0K Sep 22 14:33 dir1   YYYdir1ZZZ
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file1  YYYfile1ZZZ
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file2  YYYfile2ZZZ
-rw-r--r-- 1 meme meme   14 Sep 22 15:45 file 3 YYYfile 3ZZZ

Объяснение

custom_command ()
{
    for i; do
        echo "YYY${i}ZZZ"
    done
}
  • Цикл for i без дальнейших уточнений будет использовать позиционные параметры.
  • Фигурные скобки необходимы для различения переменной i, иначе bash неправильно истолкует $iZZZ как переменную.

Пример вывода:

$ custom_command a b c
YYYaZZZ
YYYbZZZ
YYYcZZZ

При использовании с *, расширение bash:

$ custom_command *
YYYdir1ZZZ
YYYfile1ZZZ
YYYfile2ZZZ
YYYfile 3ZZZ

Команда “ls -lh” обычно делает следующее:

$ ls -lh
total 16K
drwxr-xr-x 2 meme meme 4.0K Sep 22 14:33 dir1
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file1
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file2
-rw-r--r-- 1 meme meme   14 Sep 22 15:45 file 3

Используя sed, 1 означает строку 1, d для удаления, чтобы убрать первую строку:

$ ls -lh | sed 1d
drwxr-xr-x 2 meme meme 4.0K Sep 22 14:33 dir1
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file1
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file2
-rw-r--r-- 1 meme meme   14 Sep 22 15:45 file 3

Программа paste и процесс замещения <(...) являются ключом к объединению этих иначе отдельных выводов. Paste обычно ожидает файлы в качестве аргументов, например, paste data1 data2. Мы используем замещение процессов bash, чтобы вывод команд выглядел как обычные файлы, с которыми он может работать, таким образом:

$ paste <( ls -lh | sed 1d ) <( custom_command * )
drwxr-xr-x 2 meme meme 4.0K Sep 22 14:33 dir1   YYYdir1ZZZ
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file1  YYYfile1ZZZ
-rw-r--r-- 1 meme meme    8 Sep 22 13:51 file2  YYYfile2ZZZ
-rw-r--r-- 1 meme meme   14 Sep 22 15:45 file 3 YYYfile 3ZZZ

Использование bashrc просто сохраняет эту команду для удобного повторного использования в новых терминалах или существующих терминалах, где вы запускаете . ~/.bashrc, чтобы перезагрузить bash.

Это не совсем пользовательский столбец для ls, но есть и другие современные альтернативы.

Оба exa и lsd позволяют значительно настраивать отображение столбцов через параметры командной строки и конфигурационные файлы.

exa имеет параметры, такие как --headers, --group или --long, и в состоянии перечислять расширенные атрибуты файла (также известные как xattrs).

lsd является другой валидной альтернативой с колонкой --blocks:

ls -l . --blocks name,size  # Возможные значения: разрешение, пользователь, группа, контекст, размер, дата, имя, inode, ссылки, git

Невозможно параметризовать команду ls(1), чтобы сделать именно это, но можно написать обертку для ls(1), чтобы выполнить запрашиваемое. Например:

#!/bin/bash

nth() { awk "{print $"$(($1+1))"}"; }

if [ ! -d "$1" ] && [ -x "$1" ]; then  # исполняемый файл предоставлен напрямую
  PATH="./:$PATH"; CMD="$1"; shift
elif [ ! -d "$1" ] && [ ! -f "$1" ] && [ -x $(which "$1")]; then
  CMD="$1"; shift
fi

[ -n "$CMD" ] && [ $# -eq 1 ] && [ -d "$1" ] && DIR="$1" || DIR="./"

ls -lhA $* | while read; do
    FILENAME=`echo "$REPLY" | nth 8`
    if [ -n "$CMD" ] && [ -f "$DIR$FILENAME" ]; then
        echo "$REPLY" `$CMD 2>/dev/null "$DIR$FILENAME"`
    else
        echo "$REPLY"
    fi
done

Теперь, при наличии необязательной команды в качестве первого аргумента, она будет вызываться для каждого файла в списке, а результат будет напечатан в столбце рядом с именем файла.

Самая простая команда +echo может выглядеть так:

echo $1

Пример команды +rotation, чтобы получить атрибут вращения EXIF из JPEG файла, может выглядеть так:

exiftool -b -Rotation $1

Пример команды +dimension, чтобы получить размер (в пикселях) изображения, может выглядеть так:

shopt -s nocasematch
nth() { awk "{print $"$(($1+1))"}"; }
if [[ $1 =~ \.JPEG$ || $1 =~ \.JPG$ ]]; then
    X=`exiftool -s -ImageSize "$1"  | nth 2`
    printf "%spx" $X
fi

Теперь сделайте +echo исполняемым (chmod +x "+echo") и протестируйте:

$ ./ls9 +echo

Вы можете написать свои команды и добавить любую информацию, которая вам интересна. Теперь возможно фильтровать строки, используя эту дополнительную информацию, например, перечислить только файлы заданных размеров или продолжительности (для видео) или только те, у которых установлен атрибут вращения и т. д.

Надеюсь, это поможет.

Ответ или решение

Для расширения команды ls -l и добавления пользовательского столбца, который, к примеру, отображал бы первую строку, полученную из команды $(CustomCommand FILE), существует несколько подходов. Ниже я опишу детально, как этого можно достичь, включая использование скриптов на Bash и альтернативные инструменты.

1. Создание обертки для команды ls

Одним из самых простых решений является создание обертки для команды ls, которая будет добавлять желаемый столбец. Вот пример, как можно реализовать это с использованием скрипта на Bash:

#!/bin/bash

custom_command() {
    # Здесь реализуется логика вашей команды, например, вывод первой строки
    head -n 1 "$1"
}

if [ "$1" = "-l" ]; then
    shift
    ls -l "$@" | while read -r line; do
        filename=$(echo "$line" | awk '{print $9}') # Получаем имя файла
        if [[ -f "$filename" ]]; then
            custom_output=$(custom_command "$filename" 2>/dev/null) # Выполнение команды и редирект ошибок
            echo "$line  $custom_output" # Вывод строки с добавленным выводом команды
        else
            echo "$line" # Если это не файл, просто выводим строку
        fi
    done
else
    ls "$@"
fi

2. Использование утилит Bash и paste

Другой пример, который демонстрирует использование утилит Bash, таких как paste и sed, чтобы создать пользовательский уровень абстракции для команды ls:

Добавьте следующее в ваш файл ~/.bashrc:

custom_command() {
    for i; do
        echo "Output of custom command for $i" # Ваш вывод
    done
}

alias ls1='paste <(ls -lh | sed 1d) <(custom_command *)'

После этого выполните команду:

. ~/.bashrc

Теперь можно запустить ls1 для получения вывода, который будет включать новый столбец.

3. Использование альтернативных инструментов

Если вам нужна более мощная функциональность, чем может предложить обертка для ls, рассмотрите возможность использования новых утилит, таких как exa или lsd. Они предлагают расширенные возможности кастомизации вывода.

Пример команды с использованием exa:

exa -l --header --long

Или с lsd:

lsd -l --blocks name,size

Заключение

Таким образом, расширение команды ls для добавления пользовательского столбца становится возможным через создание оберток на Bash или использование современных альтернатив. Эти подходы позволяют адаптировать вывод с учетом ваших потребностей, что делает работу с файлами более удобной и индивидуализированной.

Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать.

Оцените материал
Добавить комментарий

Капча загружается...