使用 awk 处理文件名/路径中带有空格的 ls 输出

使用 awk 处理文件名/路径中带有空格的 ls 输出

所有,
我有一个脚本,在其中使用 find 命令过滤出给定文件夹中的所有 png 文件并列出它们及其大小。我想要以下格式的输出:

 someFile.png => 1.2K 

我正在使用 awk 来获取 $5(以人类友好格式的文件大小)和 $9(路径)。这是我目前正在使用的:

 find "$somePath"  -iname "*.png" -print0 | xargs -0 ls -lh  | awk '{print $9,"=>",$5}'

有时文件名或路径有空格,这会使脚本出错。以下是示例输出:
/Users/test/Desktop/Test/image1 => 1.2K
/Users/test/Desktop/Test/image1.png => 1.4K

输出中的第一个条目是一个名为“image1 test.png”的文件。我在某处读到不应解析 ls 输出。解决这个问题的最佳方法是什么?

答案1

通常,可以使用 exec 使 find 执行您想要的操作,而不是通过管道将输出传递到其他程序。

find "$somePath" -iname "*.png" -printf '%p => %s\n'

如果你确实需要人性化的尺寸,那么它会稍微复杂一些:

find "$somePath" -iname "*.png" -exec printf '{} => ' \; -exec sh -c 'ls -sh "{}" | cut -f1 -d\  ' \;

注意,最后一个是 parsing ls,但据我所知,第一列中不可能出现空格;因为我们在这里只获取第一列,并且因为我们一次对单个条目(而不是列表)进行操作,所以没关系。否则,您可以使用其他程序来显示尺寸。在 BSD 和 Linux 上,您可以使用stat;在 Solaris 上,您可能必须编写自己的程序才能仅输出文件的大小。

重要的是你总是可以用来find执行任何你想要的东西,传递它完整的文件名- 这样您就不会尝试从没有良好分隔符的列表中提取文件名。

答案2

最方便的方法是使用 find 中的 printf ,但它并不完全是您正在寻找的选项。 %k 以 K 为单位打印大小,但大小是在磁盘上分配的,因此根据您的设置,这可能始终是 4k 的倍数(就像在我的系统上一样)或类似的值:

find  -name "C*.png" -printf "%f => %k \n"

CalculatorVergleich.png => 28 
ClassifierImage.png => 8 
ClassifierImage.png => 8 

有一个以字节为单位的选项:

find  -name "C*.png" -printf "%f => %s \n"
CalculatorVergleich.png => 26256 
ClassifierImage.png => 6313 
ClassifierImage.png => 6473 

%b 表示占用的 512b 块:

find  -name "C*.png" -printf "%f => %b  \n" 
CalculatorVergleich.png => 56  
ClassifierImage.png => 16  
ClassifierImage.png => 16  

也许它对你有用?文件名中的空格不应该有问题。

答案3

我假设您想要使用 awk 来处理 ls -l 以获取 ls -l 提供的附加信息。一般来说,find 和 stat 会给出更可重复的结果,但请随意使用 ls。

ls -l 所做的一件好事是它具有固定宽度,因此您可以使用 substr 作为行的开头,然后不指定长度,这将包括直到行尾的所有字符。

在下面的示例中,我将文件名分配给一个字符串,然后用下划线替换空格。我通常使用 awk 进行进一步分析,因此清除文件名中的空格使分析更容易,最终结果交给人类。

$ ls -al | awk '{myfilename=substr($0, 57);gsub(/ /,"_",myfilename);print myfilename}'

使用 find,我通常会在几个小时的过程中抓取文件系统,并保存所有文件的统计信息,然后提取关键字段以供以后分析。

myPath="./"
find "$myPath" -type f  -print0  |  xargs -0 stat   -c"%W %w %Y %y %X %x %9s %n" > myTemp.txt
cat myTemp.txt | awk '{myfilename=substr($0, 152);gsub(/ /,"_",myfilename);printf "%s %s %12s %s\n", $6,$10,$13,myfilename}'

另外,现在空格是下划线,我可以对文件名的结果进行排序,而无需重新排列排序的列。

| sort -k 4

相关内容