有没有一种直接的方法可以根据 macOS 中的 Finder 标签颜色为 ls 输出着色?

有没有一种直接的方法可以根据 macOS 中的 Finder 标签颜色为 ls 输出着色?

我有一个客户端,它的目录树包含许多我需要在本地开发机器上保存的高级目录。除非出现问题,否则我很少查看它们。

我在 Finder 中用灰色标签标记了“不感兴趣”的文件夹,用绿色标签标记了每天使用的文件夹。在我偶尔使用 Finder 时,这种方法效果很好。

相反,我使用 Terminal.app,尽管我并不反对其他终端仿真器,只要它们速度快且功能强大。使用 时ls,即使使用@G标志,我也没有有用的信息可以用来淡化不感兴趣的目录条目。(如果我可以ls通过管道传输一个简单的awk脚本来应用颜色,我会对此感到满意。)

我知道我可以使用 osascript 来获取此属性,然后修饰文件输出,但这可能会导致ls自 Unicos 以来最慢的实现。我还知道我可以使用 ls 更改默认颜色,但这还不能达到我需要的程度。

有没有一个简单、快速的工具,可以根据 Finder 标签颜色为 ls 输出着色,并且然后回到$LSCOLORS?或者这是我的下一个 GitHub 项目?

答案1

可以从com.apple.FinderInfo扩展属性中获取颜色信息。

$ xattr -p com.apple.FinderInfo filename
00 00 00 00 00 00 00 00 00 0C 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

第一行,第十个字节,位 3-1(即二进制值为 2、4 和 8 的位)。示例输出针对的是红色文件,没有设置其他值。

如果属性不可用或者半字节为0,则其为无色。

上下文菜单中从左到右的可能值顺序为: 0(无色)、C(红色)、EA4862(灰色)。

记得检查1最后一位的可能值,也3就是灰色+一些其他属性。


一种可能的解决方案如下:

定义一个函数ls~/.bash_profile如果没有给出参数,它会做一些稍微不同的事情:

function ls {
        if [ "$#" = "0" ] ; then
                find . -maxdepth 1 -exec ~/Library/Scripts/colorize.sh '{}' \;
        else
                $( which ls ) $@
        fi
}       

colorize.sh可能看起来像下面这样,调用 Python 脚本并根据其输出打印文件名:

#!/bin/bash

filename=$1

if [ ! -e "$filename" ] ; then
    exit
fi

filename="$( basename "$filename" )"

attrs=( $( $( dirname $0 )/attrs.py "$filename" | cut -f2 ) )

hidden=${attrs[0]}

if [ "$hidden" = "True" ] ; then
    exit
fi

color=${attrs[1]}

case "$color" in
    "none" )
        format="setab 8"
        ;;
    "red" )
        format="setab 1"
        ;;
    "orange" )
        format="setab 1"
        ;;
    "yellow" )
        format="setab 3"
        ;;
    "green" )
        format="setab 2"
        ;;
    "blue" )
        format="setab 4"
        ;;
    "purple" )
        format="setab 5"
        ;;
    "gray" )
        format="setab 7"
        ;;
esac

echo "$( tput $format )$filename$( tput sgr0 )"

attrs.py在同一目录中提取相关文件属性:

#!/usr/bin/env python

from sys import argv, exit
from xattr import xattr
from struct import unpack

if len(argv) < 2:
    print('Missing filename argument!')
    exit(1)

attrs = xattr(argv[1])

try:
    finder_attrs= attrs[u'com.apple.FinderInfo']

    flags = unpack(32*'B', finder_attrs)

    hidden = flags[8] & 64 == 64
    color = flags[9] >> 1 & 7
except:
    hidden = False
    color = 0

colornames = { 0: 'none', 1: 'gray', 2 : 'green', 3 : 'purple', 4 : 'blue', 5 : 'yellow', 6 : 'red', 7 : 'orange' }

print 'hidden:\t', hidden
print 'color:\t', colornames[color]

这里我没有足够多的匹配颜色选择,所以红色和橙色都用红色印刷。

在此处输入图片描述

在此处输入图片描述

hidden在这里添加了属性,因为我感兴趣的ls在修改输出的那部分。if如果您不想要它,只需删除该语句即可。

答案2

感谢@DanielBeck 的详细回答。

这是一个非常快速而又粗糙的解决方案,可用于快速检查 ssh 上某些文件的标签:

#!/bin/bash

color_08=$'\e[44;30m' #blue
color_02=$'\e[47;30m' #gray
color_04=$'\e[42;30m' #green
color_0E=$'\e[46;30m' #orange/cyan
color_06=$'\e[45;30m' #purple
color_0C=$'\e[41;30m' #red
color_0A=$'\e[43;30m' #yellow
color_00=$'\e[m'
end=$'\e[K\e[m'

for f in *; do
    x=$(xattr -p com.apple.FinderInfo "$f" 2>/dev/null)
    x=${x:27:2}
    x=color_${x:-00}
    echo "${!x}$f$end"
done

警告:不要以任何专业的形式使用它,也不要将它用于其他人提供的任何文件,因为它使用了 shell 间接,这与 eval 一样糟糕。

此外,颜色是根据我的特定配色方案 (Solarized Light) 选择的。您可能需要调整转义序列以适合您的方案。

这是一个测试文件夹:

测试文件夹

以下是我的脚本的效果:

脚本输出

橙色变成了青色,因为这是终端提供的。

是的,现在是 2016 年了,他们必须从我冰冷、麻木的手指间夺走 OS X 10.8 :-)

相关内容