通过将某些文件的名称与文本文件中的列表部分匹配来复制某些文件

通过将某些文件的名称与文本文件中的列表部分匹配来复制某些文件

我有一个目录,其中的文件的字符串名称均以 5 个数字开头(即 12345_a_b、23456_s_a),并且在同一目录中还有一个文本文件,其中包含以相同方式命名的文件名列表,但只有数字匹配,下划线后的任何内容都不匹配(即 12345_q_p、23456_p_l)。我想将当前目录中的文件复制到一个新目录中,但只有文件名的前 5 个数字与文本文件中每个文件名的前 5 个数字匹配的文件才行,而忽略后面的所有内容。似乎我可以使用 xargs,但我不确定如何部分匹配名称。有人可以帮忙吗?

答案1

遍历以_作为的行IFS,获取所需的包含数字的第一部分,然后复制以这些数字开头的文件:

shopt -s nullglob
while IFS=_ read -r i _; do [[ $i =~ ^[0-9]{5}$ ]] && echo cp -it dest/ "${i}"*; done <file.txt

展开:

#!/bin/bash
shopt -s nullglob  ##Expands to null string if no match while doing glob expansion,
                   ##rather than the literal
while IFS=_ read -r i _; do  ##Iterate over the lines of file.txt, 
                              ##with `_` as the `IFS` i.e. word splitting 
                              ##happens on each `_` only, variable `i` 
                              ##will contain the digits at start; `_` is a
                              ##throwaway variable containing the rest
    [[ $i =~ ^[0-9]{5}$ ]] \ ##Check if the variable contains only 5 digits
      && echo cp -it /destination/ "${i}"*  ##if so, copy the relevant files starting with those digits
done <file.txt

file.txt用实际的源文件和/destination/实际的目标目录替换。以下echo是用于进行试运行的命令;如果对要运行的命令满意,只需删除echo

shopt -s nullglob
while IFS=_ read -r i _; do [[ $i =~ ^[0-9]{5}$ ]] && cp -it dest/ "${i}"*; done <file.txt

答案2

以下命令应该可以解决问题,如果愿意的话,您可以在 while 循环内将前几个变量赋值与它们的文字值进行交换。

#!/bin/bash
source_dir=/directory/containing/files
target_dir=/new/directory
list=/full/path/to/number_list
reg='^[0-9]{5}$' 

while IFS= read -r line; do
   line=${line:0:5}
   [[ "$line" =~ $reg ]] && cp -t "$target_dir" "$source_dir"/"$line"* 2>/dev/null
done < "$list"
  • read命令将逐行读取您的文件,并将每行的内容设置到变量“line”中。
  • cp命令用于-t设置要复制文件的目标,并且 glob 模式"$source_dir"/"$line"*将在源目录中找到以行变量中的数值开头的任何文件。
  • 循环while意味着对列表文件的每一行执行read和命令。意味着如果列表文件中有空格,它们将包含在搜索字符串中,在这个例子中这不是直接必要的,但当您想要逐行读取文件时通常很有用。cpIFS=

答案3

对文件运行一个循环。在循环中,使用 确定文件名是否与文本文件中的文件名匹配grep

&& cp如果发现某些内容,可以使用 -q 来使用。

#!/bin/bash
while IFS= read -r file; do
  grep -Eq "^${f:0:5}" your_text_file && cp ${file} /path/to/destination/
done <( (find . -type f -regex "^[0-9]{5}.*")

当你有大量文件时,这会有一些开销。但也可以用于更复杂的任务...

相关内容