【问题标题】:How do I check if files in my folder coincide with the file names specified in my .csv file?如何检查文件夹中的文件是否与 .csv 文件中指定的文件名一致?
【发布时间】:2021-05-10 08:18:49
【问题描述】:

我正在尝试构建一个方法来检查我的 .csv 文件中的文件名是否与我的实际文件夹中的文件名匹配。如果它们不匹配,我想删除 .csv 文件中的整行。到目前为止,这是我尝试过的:

dir_path = Path('D:\audio_files')
    
csv_file_path = Path('D:\metadata.csv') 

lines = list()
files = list()

for f in os.listdir(dir_path):
    f = f.strip('.wav')
    files.append(str(f))

with open(csv_file_path, 'r') as read_file:
    reader = csv.reader(read_file)
    for row in reader:
        lines.append(row)
        for field in row:
            for f in files:
                if field != f:
                    print("Line Removed.")
                    lines.remove(row)

但是,我不断收到此错误:

Traceback (most recent call last):
File "file_checker.py", line 26, in <module>
lines.remove(row)
ValueError: list.remove(x): x not in list

我应该解决什么问题才能让它工作?

编辑:

这是我的 .csv 文件的一个小样本。这是非常直接的。第一列包含不带扩展名的文件名,第二列包含文件名的标签。

fname label
236421 Male_speech
124818 Female_speech
426906 Male_speech

等等。

我基本上是在尝试将 fname 列中的名称与我的文件夹中的名称(扩展名为 .wav)相匹配,如果名称不存在于文件夹,删除不存在的文件名所在的行。

编辑#2:

我设法通过一些本地帮助解决了这个问题。这是最终产品:

dir_path = 'D:\audio'

csv_file_path = 'D:\original.csv'

#create a new file that contains the fnames on the cvs file that match the file names in my file folder
csv_new_file = open('D:\new.csv', 'w', newline="")

# create a writer variable that will allow me to write rows in my new csv file
csv_write = csv.writer(csv_new_file, delimiter=',', quotechar='"')

# "i" variable will allow me to write the headers from the original csv file
i = 0
with open(csv_file_path, 'r') as read_file:
    reader = csv.reader(read_file, delimiter=',', quotechar='"')
    for row in reader:
#If the row is the very first, the write it as is (headers)
        if i == 0:
            csv_write.writerow(row)  
            i += 1
            continue
#Check if the file path for my audio files with .wav extension exists and the write the row of the original csv in my new csv
        file_path = dir_path + '/' + row[0] + '.wav'
        if os.path.exists(file_path):
            csv_write.writerow(row)

#IMPORTANT to close files once finished!
csv_new_file.close()
read_file.close()

【问题讨论】:

  • 错误是正确的,因为您正在遍历每一行中的字段,当字段与文件名不匹配时,您的代码会多次尝试删除该行。删除第一次成功,但后续尝试失败。
  • 您能否在问题中粘贴一个 metadata.csv 样本?
  • @jrd1 我明白了。您是否建议我应该删除遍历 csv 文件中的字段的循环之外的行?
  • @JazminCristina:是的;您可以有一个变量(例如found),用于跟踪文件名是否在行的字段中 - 即在您的第一次编辑中位于lines.append(row) 的正下方。这可以设置为默认值False,如果在lines 中找到该字段的值,则设置为True。因此,在遍历行的字段之后,您可以检查 found 是否为 True 并从您的 lines 变量中删除该行,并将找到的重置为 False。该想法的一种变体是仅当根据先前的建议找到该字段时才添加该行,这实际上会产生相同的结果。

标签: python csv file


【解决方案1】:

考虑这个块:

for f in files:
    if field != f:
        lines.remove(row)

意思是如果 field 的值不等于 f 的值,则删除它。好吧,如果 files 是文件列表,除非列表中的第一个元素与字段的值匹配,否则它将被删除,并且在该元素已被删除后迭代将继续。

我建议将files 设置为集合并检查集合中的成员身份

dir_path = Path('D:\audio_files')
    
csv_file_path = Path('D:\metadata.csv') 

lines = list()
files = set()

for f in os.listdir(dir_path):
    f = f.strip('.wav')
    files.add(str(f))

with open(csv_file_path, 'r') as read_file:
    reader = csv.reader(read_file)
    for row in reader:
        lines.append(row)
        for field in row:
            if field not in files:
                lines.remove(row)
                continue

我会亲自拆分这些循环并构建行列表,然后迭代删除元素的副本,但这可能只是个人喜好。

【讨论】:

  • 如果同一个row中的多个fields不在files中,这会抛出同样的错误。我建议在lines.remove(row) 之后添加continue
  • @MitchellOlislagers 完全正确,已修复。
  • 这更接近我正在寻找的东西,只是不完全是。我测试了建议的更改,并且不断弹出相同的错误。也许我应该删除 for 循环之外的行?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-03
  • 2011-11-15
  • 1970-01-01
  • 2010-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多