我试图在函数中运行脚本,然后调用它

filedetails ()
{
   # read TOTAL_DU < "/tmp/sizes.out";
    disksize=`du -s "$1" | awk '{print $1}'`;
    let TOTAL_DU+=$disksize;
    echo "$TOTAL_DU";
   # echo $TOTAL_DU > "/tmp/sizes.out"
}

im使用变量total_du作为计数器来计数所有文件的du
我使用parallel或xargs运行它
find . -type f | parallel -j 8 filedetails

但是,变量total_du每次都会重置,并且不会保持计数,这与每次使用新shell时的预期一样。
我也试过使用一个文件来导出然后读取计数器,但是由于并行,有些文件的速度比其他文件快,所以它不是顺序的(如预期的那样),所以这是不好的……
在使用parallel或xargs时是否有方法保持计数

最佳答案

除了学习目的之外,这不太可能是对parallel的良好使用,因为:
像这样调用du可能会比以正常方式调用du慢得多。首先,可以从目录中提取有关文件大小的信息,这样就可以在一次访问中计算出整个目录。有效地,目录被存储为一种特殊的文件对象,其数据是目录实体的向量(“dirents”),其中包含每个文件的名称和元数据。您所做的是使用find打印这些目录,然后让du解析每个目录(每个文件,而不是每个目录);几乎所有的第二次扫描都是多余的工作。
坚持检查每个文件可以避免重复计算同一文件的多个硬链接。所以你可以很容易地以这种方式结束膨胀磁盘的使用。另一方面,目录也占用磁盘空间,通常du会在其报告中包含此空间。但是你永远不会在任何目录上调用它,所以你最终会低估磁盘的总使用量。
为每个文件调用一个shell和一个du实例。通常,您只能为单个du创建单个进程。进程创建比从目录中读取文件大小慢得多。至少,您应该使用du并重写shell函数来对所有参数调用parallel -X,而不仅仅是du
无法在同级shell之间共享环境变量。因此,必须将结果累积到持久性存储中,如临时文件或数据库表。这也是一个代价高昂的操作,但是如果您采纳了上述建议,那么每次调用$1,您只需要执行一次,而不是对每个文件执行一次。
所以,忽略前两个问题,只看后两个问题,仅仅是为了说教,你可以做如下事情:

# Create a temporary file to store results
tmpfile=$(mktemp)
# Function which invokes du and safely appends its summary line
# to the temporary file
collectsizes() {
  # Get the name of the temporary file, and remove it from the args
  tmpfile=$1
  shift
  # Call du on all the parameters, and get the last (grand total) line
  size=$(du -c -s "$@" | tail -n1)
  # lock the temporary file and append the dataline under lock
  flock "$tmpfile" bash -c 'cat "$1" >> "$2"' _ "$size" "$tmpfile"
}
export -f collectsizes

# Find all regular files, and feed them to parallel taking care
# to avoid problems if files have whitespace in their names
find -type f -print0 | parallel -0 -j8 collectsizes "$tmpfile"
# When all that's done, sum up the values in the temporary file
awk '{s+=$1}END{print s}' "$tmpfile"
# And delete it.
rm "$tmpfile"

关于linux - 在函数中维护变量-全局变量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29042259/

10-10 17:45