假设我的目录Historic_Documents
有以下文件/大小:
Declaration_of_Independence.txt
342 字节Magna_Carta.txt
1580 字节Treaty_of_Versaille.txt
752 字节。
是否可以仅使用ls
命令来获取以下输出?
342 Declaration_of_Independence.txt
1580 Magna_Carta.txt
752 Treaty_of_Versaille.txt
答案1
如何使用ls -l
while 循环解析详细列表的输出:
我看了看这个问题,觉得这是一件你可以很容易做到的事情寻找:
$ find -maxdepth 1 -type f -printf '%s %f\n'
或者
#!/bin/bash
for i in *; do
stat --format '%s %N' "$i"
done
(%N 将尊重 QUOTING_STYLE 环境变量;默认为“shell-escape”)。
获取大小的唯一方法ls
是通过详细列表。通过使用read
读取ls
输出;在分配给变量之前,单词的前导和尾随空格将被删除,第一个单词分配给第一个变量,依此类推,当所有变量都分配后,剩余的单词将添加到最后一个变量,这样我们就可以 保存文件名上有空格。
#!/bin/bash
while read -r p c u g s e n; do
[[ $p = total ]] && continue || { echo -n "$s "; eval "ls -d $n"; }
done < <(ls -Lpl --time-style=+%s --quoting-style=shell-escape)
(使用echo -n "$s "; eval "ls -d $n"
有点多余,但它展示了如何将“shell-escape”与其他命令一起使用。如果您只想显示大小和名称的输出,请使用 echo "$s $n"
)
读取变量:
-rwxr-xr-x 1 bac0n bac0n 209 1572207800 script.sh
^ ^ ^ ^ ^ ^ ^
p c u g s e n
ls选项:
-L
显示符号链接的文件信息时,显示链接引用的文件的信息而不是链接本身的信息。-p
将 / 指示符附加到目录。-l
使用长列表格式。--time-style
使用 -l 的时间/日期格式;在脚本中将其设置为纪元是一种很好的做法。--quoting-style
使用 POSIX 建议的 '$''' 语法引用不可打印字符。
测试目录:
$ ls
a 'b'$'\r''c' 'd'$'\n''e' "f'g" h,i 'j k' 'l m' 'n ' ' o'
答案2
仅使用ls
选项,您就可以执行以下操作:
ls -sd --block-size=1 --format=single-column *
以下是选项:
-sd
说打印分配的文件大小在块中,该d
选项从输出中删除目录“总计”行--block-size=1
每单位大小打印 1 个字节(而不是 K)--format=single-column
说将结果打印为单列*
表示在当前目录中的所有文件上运行,并且在使用该选项ls
时需要d
假设您当前的目录是Historic_Documents
。
编辑:
因为你想要文件内容的大小,所以我认为你不能只用ls
选项来做到这一点。但是,你可以使用它du
来获得你想要的精确结果:
du -b *
-b
或选项--bytes
以字节为单位打印实际文件大小,这也相当于选项:--apparent-size --block-size=1
。
表观大小是文件的大小(类似于列出的大小ls -l
),而不是分配的文件大小或磁盘使用情况。
答案3
仅使用ls
,没有,但是使用 stat
(如果您有ls
)stat
:
stat -c "%s %n" *
stat
使用格式(-c
,--format
)是获取文件数据最灵活的方式虽然手册页中没有明确说明,但您可以在字段上使用宽度和精度说明符,例如在 8 列上列出大小:
stat -c "%8s %n" *
答案4
更新 2
下面是使用 的单行代码awk
,它的好处是还可以保留文件名中的多个连续空格:
ls -l | awk 'BEGIN{FPAT="([[:space:]]*[^[:space:]]+)"; OFS = "";} FNR == 1 {next} {$1=$2=$3=$4=$6=$7=$8=""}1'
FPAT="([[:space:]]*[^[:space:]]+)"
用于设置字段应为的正则表达式。在这里,我们将字段设置为包含零个或多个空格字符,以及除空格之外的所有其他字符。关于使用的建议FPAT
可以在这个 Stack Overflow 上的答案。OFS = ""
用来使得输出只有一个空格作为字段分隔符(另一个空格由文本操作添加)。FNR == 1 {next}
ls -l
这样做的目的是,不会打印开头的空白行(对应于显示已使用块总数的输出的第一行) 。{$1=$2=$3=$4=$6=$7=$8=""}1
清空指定的字段并打印其余部分,即第五个字段(文件大小)和第九个直到最后(文件名)。
需要注意的是,上述命令输出的每一行都会有一个或多个前导空格。在我看来,这会使输出更易于阅读,但是,您可以通过将命令传输awk
到sed
以下命令来删除前导空格(*
从命令中删除sed
以仅删除一个前导空格):
ls -l | awk 'BEGIN{FPAT="([[:space:]]*[^[:space:]]+)"; OFS = "";} FNR == 1 {next} {$1=$2=$3=$4=$6=$7=$8=""}1' | sed 's/^ *//'
更新
更好的方法是cut
在输出上使用ls -l
:
ls -l | tr -s ' ' | cut -d ' ' -f 5,9-
这里,tr -s ' '
用于将ls -l
输出的字段之间的多个空格压缩为一个,然后cut
使用空格作为分隔符来显示输出的第五个字段(文件大小)和第九个字段(文件名)之后的所有字段ls -l
。
但请注意,如果您的文件名包含多个连续的空格,它们将显示为单个空格,因为tr
(谢谢 bac0n)。
你可以使用这个:
ls -sh
-s
(或--size
):以块为单位打印每个文件的分配大小。-h
(或--human-readable
)以人类可读的格式打印大小(即分别使用 K、M 等表示千、百万等)。
您可以通过在终端中ls
运行或访问来阅读手册页以获取更多信息man ls
Ubuntuls
在线手册页。