简体   繁体   English

在 Linux 中查找并复制包含模式的多个文件

[英]FInd and copy multiple files that contain a pattern in Linux

When I need to copy multiple files in the same dir I can just:当我需要在同一个目录中复制多个文件时,我可以:

  • cp file{20..30} newLocation cp文件{20..30} newLocation

But when I combine that with find, it doesn't work.但是当我将它与 find 结合起来时,它不起作用。

  • find .寻找 。 -name ' file{20..30} ' -exec cp '{}' newLocation ';' -name '文件{20..30} ' -exec cp '{}' newLocation ';'

What am I doing wrong?我究竟做错了什么?

The {20..30} range syntax is a special feature of Bash's command-line parser. {20..30}范围语法是 Bash 命令行解析器的一个特殊功能。 It is not part of standard POSIX globbing, such as find 's -name test performs, and it's not even recognized by Bash in some contexts where you might like it to be.它不是标准 POSIX globbing 的一部分,例如find-name测试执行,并且在您可能喜欢的某些上下文中,Bash 甚至无法识别它。

You already know the simpler, more direct alternative that I would otherwise recommend for your example case.您已经知道我会为您的示例案例推荐的更简单、更直接的替代方案。 You could also do something like你也可以做类似的事情

find . '(' -name 'file2[0-9]' -o -name file30 ')' -exec cp '{}' newLocation ';'

, though that doesn't work very well if the endpoints of the range are determined dynamically. ,但如果范围的端点是动态确定的,则效果不佳。

If the point of using find is to avoid problems arising from some of the files not existing, then you might consider addressing it like this:如果使用find是为了避免一些不存在的文件引起的问题,那么您可以考虑像这样解决它:

for f in file{20..30}; do
    [[ -e "$f" ]] && cp "$f" newLocation
done

As mentioned from the other post/answer, enclosing the names with a ( and closing ) plus the -o and -name in between.正如其他帖子/答案中所述,用(和结束)加上-o-name将名称-name起来。

Something like this should be able to add those strings from your input file/string.像这样的东西应该能够从您的输入文件/字符串中添加这些字符串。

#!/usr/bin/env bash

format() {
  local f
  declare -ag files
  for f; do
    files+=( -o -name "$f" )
  done
}

format file{10..20}

Now check the value of "${files[@]}"现在检查"${files[@]}"

declare -p files

Output输出

declare -a files=([0]="-o" [1]="-name" [2]="file10" [3]="-o" [4]="-name" [5]="file11" [6]="-o" [7]="-name" [8]="file12" [9]="-o" [10]="-name" [11]="file13" [12]="-o" [13]="-name" [14]="file14" [15]="-o" [16]="-name" [17]="file15" [18]="-o" [19]="-name" [20]="file16" [21]="-o" [22]="-name" [23]="file17" [24]="-o" [25]="-name" [26]="file18" [27]="-o" [28]="-name" [29]="file19" [30]="-o" [31]="-name" [32]="file20")

To see what would it look like when used as an input to find看看当用作find的输入时它会是什么样子

printf '%s\n' "\( ${files[*]} \)"

Output输出

\( -o -name file10 -o -name file11 -o -name file12 -o -name file13 -o -name file14 -o -name file15 -o -name file16 -o -name file17 -o -name file18 -o -name file19 -o -name file20 \)

To use that array files as an input to find将该数组files用作find的输入

find . -type f \( "${files[@]:1}" \) -exec bash -c 'echo cp -v -- "$@" /destination' _ {} +
  • The "${files[@]:1}" removes the leading -o "${files[@]:1}"删除前导-o

  • Remove the echo if you're satisfied with the output so files copying should occur.如果您对输出感到满意,请删除echo ,以便进行文件复制。


Or just use globstar with nullglob '或者只是使用globstarnullglob '

#!/usr/bin/env bash

shopt -s globstar nullglob

cp -v ./**/file{10..20} /destination

The leading ./ means the current directory, It could be前导./表示当前目录,可以是

/path/to/source/**/file{10..20}

where /path/to/source/ is the directory where the files in question are.其中/path/to/source/是相关文件所在的目录。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM