Bash:仅抓取输出的第二行和最后一行(ls -lrS)

Bash: grabbing the second line and last line of output (ls -lrS) only

我正在寻找 ls -lrS 命令输出的第二行和最后一行。我一直在用 ls -lrS | (head -2 | tail -1) && (tail -n1) 但是好像只得到第一行,我必须按 control C 才能停止它。

我遇到的另一个问题是使用 awk 命令,我只想获取文件大小和文件名。如果我要得到正确的行(第二行和最后一行),我想要的输出将是

files=$(ls -lrS | (head -2 | tail -1) && (tail -n1) awk '{ print "%s", ; "%s", ; }' )

我希望它会打印:

1234 file.abc

12345 file2.abc

使用awk

ls -lrS | awk 'NR==2 { print; } END { print; }'

print 当行号 NR 为 2 并再次出现在最后一行时。

注意: 正如评论中指出的,[=14=] 可能会或可能不会出现在 END 块中,具体取决于您的 awk版本。

ls 不是这项工作的可靠工具:它不能表示所有可能的文件名(space 是可能的,但换行符和其他特殊字符也是可能的——除了 NUL 之外的所有字符) .在具有 GNU 工具的系统上,一种可靠的解决方案是使用 find:

{
    # read the first size and name
    IFS= read -r -d' ' first_size; IFS= read -r -d '' first_name;

    # handle case where only one file exists
    last_size=$first_size; last_name=$first_name

    # continue reading "last" size and name, until one really is last
    while IFS= read -r -d' ' curr_size && IFS= read -r -d '' curr_name; do
      last_size=$curr_size; last_name=$curr_name
    done
} < <(find . -mindepth 1 -maxdepth 1 -type f -printf '%s %P[=10=]' | sort -n -z)

上面将结果放入变量$first_size$first_name$last_size$last_name,因此可用:

printf 'Smallest file is %d bytes, named %q\n' "$first_size" "$first_name"
printf 'Largest file is %d bytes, named %q\n' "$last_size" "$last_name"

就其运作方式而言:

find ... -printf '%s %P[=12=]'

...从 find 发出以下形式的流:

<size> <name><NUL>

运行 通过 sort -n -z 的流对其内容进行数字排序。 IFS= read -r -d' ' first_size 读取所有内容直到第一个 space; IFS= read -r -d '' first_name 读取所有内容直到第一个 NUL;然后循环继续读取和存储额外的 size/name 对,直到到达最后一个。

使用格式稳定的 GNU stat 命令:

stat --format='%s %n' * | sort -n | sed -n '1p;$p'

如果您使用的是 BSD stat,请相应地进行调整。

如果您想更好地控制哪些文件进入此计算,并且可以说是更好的可移植性,请使用 find。在此示例中,我将获取当前目录中的所有非点文件:

find -maxdepth 1 -not -path '*/\.*' -printf '%s %p\n' | sort -n | sed -n '1p;$p'

如果您的目录包含两个或更少的条目,或者您的任何条目的名称中是否有换行符,请注意。

whatever | awk 'NR==2{x=[=10=];next} {y=[=10=]} END{if (x!="") print x; if (y!="") print y}'

您需要这种复杂性(以及更多才能真正稳健)来处理少于 3 行的输入。