R:从目录中查找其名称包含特定字符串并与我的通缉文件列表匹配的文件

R: locating files that their names contain a specific string from a directory and match to my list of wanted files

我又是新手,文件和文件夹情况又是一团糟(感谢我们生物学家):我得到了这个包含大量.txt文件(~900,000+)的目录,所有文件之前都已经处理过命名格式不一致:(

例如,目录中的杂乱文件如下所示:

ctrl_S978765_uns_dummy_00_none.txt
ctrl_S978765_3S_Cookie_00_none.txt
S59607_3S_goody_3M_V10.txt
ctrlnuc30-100_S3245678_DMSO_00_none.txt
ctrlRAP_S0846567_3S_Dex_none.txt
S6498432_2S_Fulra_30mM_V100.txt
.....

如您所见,命名没有可靠的一致性。对我来说重要的是嵌入其中的 ID 代码,例如 S978765。现在我得到了我想要的这些 ID 代码的列表(100 个 ID 代码)。

包含如下列表的 CSV 文件,请注意,由于第二列中的 CLnumber 值不同,该列表在行中确实有重复的 ID 代码:

ID code  CLnumber
S978765  1
S978765  2
S306223  1
S897458  1
S514486  2
....

所以我想完成以下任务:通过匹配到我的列表,使用代码 ID 找到所有乱七八糟的命名文件。并将它们复制到一个新目录中。

我想过使用 list.files() 来获取所有的 .txt 文件及其名称,然后我在下一步匹配代码 ID 名称时卡住了,我知道如何做到这一点一个字符串,比如说 "S978765",但是如果我一个一个地做,这几乎就像手动挖掘文件夹一样。

如何将column1中的ID代码名称作为列表输入,然后compare/match将它们与目录中的乱七八糟的文件标题名称一起复制到新文件夹中?

非常感谢, 毫升

这个有效:

library(stringr)

# get this via list.files in your actual code
files <- c("ctrl_S978765_uns_dummy_00_none.txt",
           "ctrl_S978765_3S_Cookie_00_none.txt",
           "S59607_3S_goody_3M_V10.txt",
           "ctrlnuc30-100_S3245678_DMSO_00_none.txt",
           "ctrlRAP_S0846567_3S_Dex_none.txt",
           "S6498432_2S_Fulra_30mM_V100.txt")

ids <- data.frame(`ID Code` = c("S978765", "S978765", "S306223", "S897458", "S514486"),
                  CLnumber = c(1, 2, 1, 1, 2),
                  stringsAsFactors = FALSE)

str_subset(files, paste(ids$ID.Code, collapse = "|"))
#> [1] "ctrl_S978765_uns_dummy_00_none.txt" "ctrl_S978765_3S_Cookie_00_none.txt"

str_subset 接受一个字符向量和 returns 个匹配某种模式的元素。在这种情况下,模式是 "S978765|S978765|S306223|S897458|S514486"(通过使用 paste 创建),它是一个 正则表达式 匹配由 [=14 分隔的任何 ID 代码=].所以我们取 files 并只保留在 ID Code 中匹配的元素。

还有很多其他方法可以做到这一点,可能会或可能不会更清楚。例如,您可以将 ids$ID.Code 直接传递给 str_subset,而不是通过 paste 构造正则表达式,但这样每次都会抛出有关对象长度的警告,这可能会造成混淆(或导致如果您习惯于忽略它然后在重要的不同上下文中忽略它,就会出现问题)。另一种方法是使用 purrrkeep,但虽然这样写起来可能更清晰一些,但效率会低得多,因为这意味着要对文件向量进行多次传递 - - 在这种情况下不相关,但如果您突然需要对数十万个文件和 ID 执行此操作,则可能非常相关。

您可以使用正则表达式从文件名中提取 ID 代码。

在这里,我使用了 "S" 后跟 5 个或更多数字的模式。一旦我们提取了 ID_codes,我们就可以将它们与我们在 csv 中的那些进行比较。

假设 csv 被称为 df 并且列名是 ID_Codes 我们可以使用 %in% 来过滤它们。

然后我们可以使用 file.copy 将文件从一个文件夹移动到另一个文件夹。

all_files <- list.files(path = '/Path/To/Folder', full.names = TRUE)
selected_files <- all_files[sub('.*(S\d{5,}).*', '\1', basename(all_files)) 
                                 %in% unique(df$ID_Codes)]
file.copy(selected_files, 'new_path/for/files')