Вопрос или проблема
Интересно, возможно ли изменить команду 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 или использование современных альтернатив. Эти подходы позволяют адаптировать вывод с учетом ваших потребностей, что делает работу с файлами более удобной и индивидуализированной.
Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать.