【问题标题】:Checking That All Files Are Present检查所有文件是否存在
【发布时间】:2015-11-29 05:11:11
【问题描述】:

我有一个关于命令行搜索方法的问题。这是我的情况。

  1. 我有一个数据文件,其中包含一堆 (~36,000) 对象的标识号,如下所示:

    # ID
    85000213
    85000234
    85000246
    85000247
    85000249
    85000250
    ...
    
  2. 我还有一个数据文件目录,其中包含有关每个对象的数据,名称如下:

    datafileID85000213.csv
    datafileID85000234.csv
    datafileID85000246.csv
    datafileID85000247.csv
    datafileID85000249.csv
    datafileID85000250.csv
    ...
    

我实际上想检查我的原始 ID 数据文件中的所有对象是否都有一个包含其实际数据的关联 CSV 文件。我这样做的第一个想法是使用 diff 命令来比较这些列表,但为了做到这一点,我需要从我拥有的 ~36,000 个 CSV 文件名中创建一个单列数据文件以便进行比较。一个复杂的问题是,对于我迄今为止尝试使用的大多数命令(mv、cp、ls),我得到了这个:

参数列表太长

有人对此任务有解决方法(或更好的主意)吗?

为了在每个文件名字符串中搜索数字,到目前为止我发现了两件事之一:

  1. 蟒蛇:

    >>> import re
    >>> idlist
    ['abcdefg0.dat', 'abcdefg1.dat', 'abcdefg2.dat', 'abcdefg3.dat', 'abcdefg4.dat', 'abcdefg5.dat', 'abcdefg6.dat', 'abcdefg7.dat', 'abcdefg8.dat', 'abcdefg9.dat']
    >>> numbers = []
    >>> for i in range(len(idlist)):
    ...     numbers.append(re.search(r'\d+',idlist[i]).group())
    ... 
    >>> numbers
    ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
    
  2. bash:UNIX BASH: extracting number from string

任何帮助将不胜感激!

【问题讨论】:

  • 在一个平面目录中处理这么多文件你不觉得麻烦吗?
  • @SylvainLeroux - 它肯定会比替代品慢,但它会起作用。
  • @msw 现代文件系统肯定可以处理每个目录中如此“大量”的文件。然而,我记得很久以前(在……嗯……Win NT4 上)被某些工具(尤其是我们的增量备份实用程序)对此的有限支持所困扰。但也许那些日子也一去不复返了?
  • @Sylvain Leroux - “平面”目录到底是什么意思?
  • @astromax:通过“flat”,Sylvain Leroux 是指将所有 36k 文件保存在一个目录中,而不是将它们拆分到多个子目录中。回到过去 (TM),一些操作系统和/或工具/程序/实用程序在处理具有如此大量文件的目录时会发出嘶哑的声音。这需要将如此大量的文件分布在多个子目录中,每个子目录的文件数不超过(最大限制)。

标签: python bash csv diff


【解决方案1】:

来自bash

{
   # Read the header into a variable, but ignore it
   read -r hdrLine
   while read -r fileID; do
      [[ -f $DIRECTORY/datafileID$fileID.csv ]] || echo "$fileID not found"
   done
} < id_list.txt

{...} 中的所有内容都从文件 id_list.txt 中读取。第一个read 语句读取并丢弃标题。然后while 循环从文件中读取剩余的行,一次一行。将DIRECTORY 设置为文件所在目录的名称(或替换为硬编码路径,您可以选择),它会检查该目录中是否存在名称为datafileID$fileID.csv 的文件。如果是这样,什么都不会发生。否则,会在标准输出中打印一条与此有关的消息。

您可以使用文件 glob 执行更一般的检查。

[[ -f $DIRECTORY/*$fileID* ]]

将检查名称中包含$fileID 的文件是否存在。

【讨论】:

  • 太好了,我的数据下载完成后我会试一试!
  • 我觉得使用test -f ... || echo ... 会比[[ ]] 更明确,但我想这并不重要。
  • 这是答案中唯一的非 POSIX 部分,因此这是使用 [test 的好理由。但我更喜欢尽可能使用[[
  • 嗯。我已经尝试过了,它告诉我不存在任何文件,这不可能是真的。你能解释一下这里到底在做什么吗?此外,最终我的文件将具有不同的名称,但其中仍会包含我要提取的一串数字。是否有一种完全通用的方法可以在文件名中搜索该数字字符串而不必事先知道文件名的形式?我想我要的是一种在 bash 中搜索正则表达式的方法。
  • 太棒了,这对我来说非常有用!感谢您的 bash 解决方案。给未来读者的注意事项 - 请注意文件所在的目录。最简单的方法是更改​​它,打印工作目录,然后将其复制到脚本或命令行中。
【解决方案2】:

这在 python 中很简单:

import os.path
with open('idfile') as fin:
     header = next(fin) #read the `#ID` comment header line.  Don't use it.
     for line in fin:
         fname = 'datafileID{0}.csv'.format(line.strip())
         if not os.path.exists(fname):
             print fname

【讨论】:

  • 数据下载完成后,我也会试一试 - 感谢您的快速响应!
  • 如果idfile和csv文件所在的目录不是当前目录怎么办? idfile 很简单,您只需在它之前添加完整路径。但是,我应该在 fname 中包含路径吗?
  • 你可以使用类似:if not os.path.exists(os.path.join(path,fname)):
  • 太棒了!这对我有用。我必须非常小心“idfile”和 csv 文件所在的目录。
【解决方案3】:

比如:

import os
root = '/path/to/files/'
with open('filelist.txt') as f:
    for line in f:
        if not os.path.exists(root+'datafileID'+line.strip()+'.csv'):
            print line

这将打印所有没有匹配文件的 ID。

【讨论】:

  • 上述解决方案的一个很好的变体。如果它不存在,我将需要返回并下载那些。谢谢!
  • 注意这里,line 将包含一个尾随换行符。
  • 好收获。在其中添加了 strip()。
【解决方案4】:

这对我来说适用于 40000 个文件:

diff <( ls -1 *.csv  | cut -c11-18 ) <( tail -n +2 idlist ) | grep '^>' | cut -d' ' -f2

输出类似于

80001234
80004321

【讨论】:

  • 输出的ID号是存在的还是不存在的?
猜你喜欢
  • 1970-01-01
  • 2013-08-02
  • 2018-09-18
  • 2018-06-19
  • 2021-12-25
  • 1970-01-01
相关资源
最近更新 更多