Bash:从ls -l读取一列

时间:2016-01-09 23:21:25

标签: linux bash shell awk

对于uni的问题,我需要获取一系列目录中5个最大文件的文件大小和文件名。要做到这一点,我正在使用两个函数,一个用ls -l加载所有东西(我意识到从ls解析信息不是一个好方法,但这个特殊问题指明我不能使用find,locate或du) 。然后将来自ls输出的每一行发送到另一个函数,该函数使用awk应该撤销文件大小和文件名并将其存储到数组中。相反,我似乎正在尝试打开ls中的每一列来阅读。 这样的代码如下:

function addFileSize {
    local y=0
    local curLine=$1
    if [[ -z "${sizeArray[0]}" ]]; then
        i=$(awk '{print $5}' $curLine)
        nameArray[y]=$(awk '{print $9}' $curLine)
    elif [[ -z "${sizeArray[1]}" ]]; then
        i=$(awk '{print $5}' $curLine)
        nameArray[y]=$(awk '{print $9}' $curLine)
    elif [[ -z "${sizeArray[2]}" ]]; then
        i=$(awk '{print $5}' $curLine)
        nameArray[y]=$(awk '{print $9}' $curLine)
    elif [[ -z "${sizeArray[3]}" ]]; then
        i=$(awk '{print $5}' $curLine)
        nameArray[y]=$(awk '{print $9}' $curLine)
    elif [[ -z "${sizeArray[4]}" ]]; then
        i=$(awk '{print $5}' $curLine)
        nameArray[y]=$(awk '{print $9}' $curLine)
    fi  

    for i in "${sizeArray[@]}"; do
        echo "$(awk '{print $5}' $curLine)"
        if [[ -z "$i" ]]; then
            i=$(awk '{print $5}' $curLine)
            nameArray[y]=$(awk '{print $9}' $curLine)
            break
        elif [[ $i -lt $(awk '{print $5}' $curLine) ]]; then
            i=$(awk '{print $5}' $curLine)
            nameArray[y]=$(awk '{print $9}' $curLine)
            break
        fi
        let "y++"
    done
    echo "Name Array:"
    echo "${nameArray[@]}"
    echo "Size Array:"
    echo "${sizeArray[@]}"
}

function searchFiles {
    local curdir=$1
    for i in $( ls -C -l -A $curdir | grep -v ^d | grep -v ^total ); do # Searches through all files in the current directory
        if  [[ -z "${sizeArray[4]}" ]]; then
            addFileSize $i
        elif [[ ${sizeArray[4]} -lt $(awk '{print $5}' $i) ]]; then
            addFileSize $i
        fi
    done
}

非常感谢任何帮助,谢谢。

5 个答案:

答案 0 :(得分:2)

如果问题特别是关于解析,那么awk可能是一个不错的选择(虽然ls输出很难可靠解析)。同样,如果问题是关于使用数组,那么您的解决方案应该关注那些。

但是,如果问题是鼓励您了解可用的工具,我建议:

  • stat 工具打印有关文件的特定信息(包括大小)
  • 排序工具重新排序输入行
  • head tail 工具打印输入的第一行和最后一行
  • 并且您的shell还可以执行路径名扩展以列出匹配glob通配符模式的文件,例如 * .txt

想象一个包含各种大小文件的目录:

  10000000 sound/concert.wav
   1000000 sound/song.wav
    100000 sound/ding.wav

您可以使用路径名扩展查找其名称:

$ echo sound/*
sound/concert.wav sound/ding.wav sound/song.wav

您可以使用 stat 将名称转换为si z e:

$ stat -f 'This one is %z bytes long.' sound/ding.wav
This one is 100000 bytes long.

与大多数Unix工具一样,无论您提供一个或多个参数,stat的工作方式都相同:

$ stat -f 'This one is %z bytes long.' sound/concert.wav sound/ding.wav sound/song.wav
This one is 10000000 bytes long.
This one is 100000 bytes long.
This one is 1000000 bytes long.

(查看man stat以获取有关%z的参考信息以及您可以打印的其他内容。文件的 N ame特别有用。)

现在你有一个文件大小列表(希望你也保留了他们的名字)。你如何找到最大的尺寸?

在排序列表中找到最大项目要比未排序列表容易得多。要了解它,请考虑如何在此未排序列表中找到最高的两项:

  

1234 5325 3243 4389 5894 245 2004 45901 3940 3255

如果对列表进行排序,您可以非常快速地找到最大的项目:

  

245 1234 2004 3243 3255 3940 4389 5325 5894 45901

Unix 排序实用程序接受输入行并从最低到最高输出(或以 r 顺序输出sort -r)。

它默认按字符排序,这对于单词很有用(“apple”在“气球”之前出现)但对数字来说不是很好(“10”在“9”之前出现)。您可以使用sort -n激活 n 数字排序。

一旦您有一个排序的行列表,您可以使用 head 工具打印第一行,或使用 tail 工具打印最后一行。

拼写检查的(已经排序的)单词列表的前两项:

$ head -n 2 /usr/share/dict/words
A
a

最后两项:

$ tail -n 2 /usr/share/dict/words
Zyzomys
Zyzzogeton

通过这些部分,您可以组合问题的解决方案“找到dir1,dir2,dir3中的五个最大的文件”:

stat -f '%z %N' dir1/* dir2/* dir3/* |  
     sort -n |  
     tail -n 5  

或者“找到dir1,dir,dir3,dir4,dir5中每个文件中最大的文件”的解决方案:

for dir in dir1 dir2 dir3 dir4 dir5; do  
    stat -f '%z %N' "$dir"/* |  
        sort -n |  
        tail -n 1  
done

答案 1 :(得分:0)

使用ls -S按大小排序,通过head进行排序以获得前五名,通过sed管道将多个空格压缩为一个,然后通过cut管道输入获取大小和文件名字段。

  罗伯特@哈瓦那:〜/ scripts $ ls -lS |头-n 5 | sed -e's / / / g'| cut -d“” - f 5,9

     

32K xtractCode.pl

     

29K tmd55.pl

     

24K tagebuch.pl

     

14K备份

只需将目录指定为初始ls的参数。

答案 2 :(得分:0)

不使用findlocatedu,您可以为每个目录执行以下操作:

    ls -Sl|grep ^\-|head -5|awk '{printf("%s %d\n", $9, $5);}'

按大小列出所有文件,过滤掉目录,占据前5位,并打印文件名和大小。在每个目录的bash中使用循环包装。

答案 3 :(得分:0)

这将是另一种选择。 Ctrl + V + I是如何从命令行插入选项卡。

ls -lS dir1 dir2 dir3.. | awk 'BEGIN{print "Size""Ctrl+V+I""Name"}NR <= 6{print $5"Ctrl+V+I"$9}'

答案 4 :(得分:0)

如果您无法使用find locatedu,那么仍然可以直接选择获取文件大小而无需求助于ls解析:

size=$(wc -c < "$file")

wc非常聪明,能够在STDIN上检测文件并调用stat来获取大小,因此效果一样快。