我正在编写一个脚本tcsh
(是的......我知道但我必须)来分析特定目录中的所有用户磁盘使用情况。
最后,我想生成以下格式的报告:
user1 1.6GB
user2 1.1GB
..
user69 10MB
首先我跑步
find . -printf "%u %s\n" | awk '{user[$1]+=$2}; END{ for( i in user) print i " " user[i]}' > example.tmp
然后我设法通过以下方式将第二列转换为人类可读的大小:
awk '{ print $2 }' example.tmp | numfmt --to=iec-i --suffix=B --padding=7
但我无法将其合并回上一专栏的位置。有没有办法numfmt
直接将命令注入awk
求和?
我对“awk”命令有点弱,所以请原谅我的糟糕代码。
答案1
您应该能够通过使用直接将格式限制为仅第二个字段--field
的选项来避免这样做,即numfmt
find . -printf "%u %s\n" |
awk '{user[$1]+=$2}; END{ for(i in user) print i, user[i]}' |
numfmt --field=2 --to=iec-i --suffix=B --padding=7
如果您确实需要在 awk 中应用numfmt
on 作为特定值,那么这里有一个适用于简单情况并且不需要的变体getline var
:
find . -printf "%u %s\n" |
awk '
{user[$1]+=$2}
END {
cmd = "numfmt --to=iec-i --suffix=B --padding=7";
for(i in user){ printf "%s ", i; print user[i] | cmd; close(cmd) }
}
'
答案2
您可以通过numfmt
从内部调用命令来实现此目的awk
,例如:
awk '{cmd=sprintf("numfmt --to=iec-i --suffix=B --padding=7 %d",$2); cmd | getline converted; close(cmd); print $1,converted}' example.tmp
这样,您也可以在第一次awk
调用中直接实现它:
find . -printf "%u %s\n" | awk '{user[$1]+=$2};
END{
for(i in user) {
cmd=sprintf("numfmt --to=iec-i --suffix=B %d",user[i]);
cmd | getline converted;
close(cmd);
printf("%s % 7s\n",i,converted)
}
}'
答案3
测试并运行良好
#!/usr/bin/python
import os
import subprocess
from os import *
users=[]
for i,j,k in os.walk('<directory>'):
for m in k:
fil=str(i)+str(m)
if os.path.isfile(fil):
if os.stat(fil).st_uid not in users:
users.append(os.stat(fil).st_uid)
for u in users:
size=0
for i,j,k in os.walk('<Directory>'):
for z in k:
fil=str(i)+str(z)
if os.path.isfile(fil):
if (os.stat(fil).st_uid == u):
size=os.stat(fil).st_size+size
cmd1="getent passwd {0}".format(u)
ou1=subprocess.Popen(cmd1,stdout=subprocess.PIPE,shell=True).communicate()[0].strip().split(':')[0]
print size,ou1
~
~