【问题标题】:To read each file and execute the func in loop [closed]读取每个文件并在循环中执行 func [关闭]
【发布时间】:2014-02-20 14:06:43
【问题描述】:

我的硬盘中有 5000 个文件,名称为 ip_file_1,ip_file_2,.... 我有一个只能合并 2 个文件的可执行文件。如何编写一个脚本来获取驻留在硬盘中的所有文件(以 ip_file_* 开头)并调用用于合并所有文件的函数。

我有 5000 个文件,它们是包含日志信息(每个函数调用所花费的时间)的二进制文件。我有另一个可执行文件,它只需要两个文件并根据时间戳合并并给出合并的输出。

我使用如下格式执行,

./trace ip_file1 ip_file2 mergefile  # I'm not using the trace tool. It's an example

我可以使用可执行文件只合并两个文件。我想自动化它来合并所有其他文件。

合并必须按顺序进行(根据时间戳合并)。合并的逻辑已经存在。并将合并的输出发送到文件中。

我的问题不在于如何合并文件。我的问题是如何自动化和合并所有文件而不是两个文件。

【问题讨论】:

  • “从标准输入获取 I/P”是什么意思?你能详细说明你想做什么吗?
  • 我在这里看到了几个问题。一个是从 stdin(wtf, RTFM, google) 获取数据,另一个是调用函数(再次,wtf),隐含的第三个是执行一系列合并(再次,微不足道)。提出一个具体问题
  • @KarolyHorvath 我认为你应该把你的评论作为答案:-)
  • @Angus 所以你想把所有 5000 个文件合并成一个文件?
  • 必须按顺序进行合并。什么样的订单?

标签: c shell


【解决方案1】:

为避免命令行参数过多或参数过长,您需要编写merge 命令,以便它可以采用先前合并的输出并合并另一个文件。原始问题陈述中merge的描述很少,所以我假设你可以这样做:

 merge -o output_file input_file

其中output_file 可以是以前合并的文件或新文件。如果你能做到这一点,那么通过以下方式合并所有它们会很简单:

find drive_path -name "ip_file_*" -exec merge -o output_file {} \;

这里的顺序是文件系统中的目录顺序。如果需要不同的顺序,则需要指定。

附录

如果您需要按时间戳顺序排列的文件,那么我会改进这种方法并创建一个merge 命令,该命令接受一个文本文件作为输入,该文本文件列出了所有要合并的文件。使用本文中提供的信息创建此文件列表:https://superuser.com/questions/294161/unix-linux-find-and-sort-by-date-modified

【讨论】:

  • Re: addendum -- 我的答案底部有一个简短的sn-p shell,它生成一个按mtime排序的文件名数组(在bash上,使用具有GNU扩展的工具)。
【解决方案2】:

如果您的外部合并工具是 real_merge,并且此工具将两个命令行参数的合并输出写入标准输出,则以下递归 shell 函数将完成这项工作:

merge_files() {
  next=$1; shift
  case $# in
    0) cat "$next" ;;
    1) real_merge "$next" "$1"
    *) real_merge "$next" <(merge_files "$@")
  esac
}

这种方法是高度并行化的——这意味着它将使用尽可能多的 CPU 和磁盘 IO。根据您的可用资源以及您的操作系统管理这些资源的能力,这可能不是一件好事。

另一种方法是使用临时文件:

swap() {
  local var_curr=$1
  local var_next=$2
  local tmp

  tmp="${!var_curr}"
  printf -v "$var_curr" "${!var_next}"
  printf -v "$var_next" "$tmp"
}

merge_files() {
  local tempfile_curr=tempfile_A
  local tempfile_next=tempfile_B
  local tempfile_A="$(mktemp -t sort-wip-A.XXXXXX)"
  local tempfile_B="$(mktemp -t sort-wip-B.XXXXXX)"
  while (( $# )); do
    if [[ -s ${!tempfile_curr} ]]; then
      # we already populated our temporary file
      real_merge "${!tempfile_curr}" "$1" "${!tempfile_next}"
      swap tempfile_curr tempfile_next
    elif (( $# >= 2 )); then
      # only two arguments at all
      real_merge "$1" "$2" "${!tempfile_curr}"
      shift
    else
      # only one argument at all
      cat "$1"
      rm -f "$tempfile_A" "$tempfile_B"
      return
    fi
    shift
  done
  # write output to stdout
  cat "${!tempfile_curr}"
  # ...and clean up.
  rm -f "$tempfile_A" "$tempfile_B"
}

如果文件名的词法排序正确,您可以将其调用为:merge_files ip_file_*。 (如果他们的名字是零填充的,这将是真的,即ip_file_00001,但如果他们没有填充,则不是真的)。如果没有,您需要先对名称流进行排序。如果您使用 bash 并且有 GNU stat 和 sort 可用,则可以这样做:

declare -a filenames=()
while IFS='' read -r -d ' ' timestamp && IFS='' read -r -d '' filename; do
  filenames+=( "$filename" )
done < <(stat --printf '%Y %n\0' ip_file_* | sort -n -z)
merge_files "${filenames[@]}"

【讨论】:

  • 跟踪产生的记录是一个接一个地用 ip_file_01,ip_file_02,.... 5000个文件)根据时间戳,我需要手动从第一个两个中取出o / p并调用合并工具将o / p与3合并,...等
猜你喜欢
  • 2018-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多