![使用 awk 处理文件名/路径中带有空格的 ls 输出](https://linux22.com/image/22641/%E4%BD%BF%E7%94%A8%20awk%20%E5%A4%84%E7%90%86%E6%96%87%E4%BB%B6%E5%90%8D%2F%E8%B7%AF%E5%BE%84%E4%B8%AD%E5%B8%A6%E6%9C%89%E7%A9%BA%E6%A0%BC%E7%9A%84%20ls%20%E8%BE%93%E5%87%BA.png)
所有,
我有一个脚本,在其中使用 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