我有数千个文件夹,其中包含文件,我想将其中一些复制到另一个目录中。我有一个.csv
包含两列的文件,其中包含文件夹名称的一部分(该文件夹包含一个字符串值或另一个字符串值,而不是两者都包含)。
- 文件夹名称示例:
PLASMA_32150129_B5/ PLASMA_AAA3891784_B3/ ...
- CSV 文件没有标题,字段之间用 分隔
,
:32150129,AAA0616938 32140203,AAA3891784 32140204,AAA0617237 32140205,AAA0617261 32140206,AAA0617285 ...
- 我发现这个小脚本作为起点:
while IFS=, read -r file rest do find /path/to/Main_directory -type d -name "${file}" -exec cp '{}' /path/to/New_directory/ \; done < mylist.csv
现在我需要指定
- csv 值只是一个模式(如
*_32150129 _*
),并且 - 我想首先尝试第一列中的模式,如果没有生成匹配项,请尝试使用另一列。
这可能吗?
谢谢你!
答案1
假设只有一列可以实际匹配,“或”类型的方法可能是可能的。为此,只需对脚本进行少量修改:
while IFS=, read -r pattern1 pattern2
do
find /path/to/start -type d \( -name "*_${pattern1}_*" -o -name "*_${pattern2}_*" \) -exec cp -r '{}' /path/to/target \;
done < filelist.csv
- 操作员
-o
将确保两个名称模式中的任何一个生成匹配。只要两者不能匹配(请参阅先决条件),这将相当于“如果第一个不存在,则第二个” - 括号(转义以防止 shell 解释)用于确保正确的运算符优先级。
- 将 shell 参数放在
-name
双引号中将确保*
保留从字面上看就在那里无需进行全局扩展(这是必要的,以便find
在搜索期间执行模式匹配,而不是在将其传递给之前的外壳find
),同时仍然允许外壳变量${pattern1}
和${pattern2}
进行扩展。 - 如果您想要复制目录及其内容,则必须使用
-r
选项。cp
答案2
最简单、最粗暴的方法,如果你曾经有过,应该会起作用一匹配文件中的每个模式,就是让 shell 完成工作:
tr , '\n' < mylist.csv |
while read pat; do cp -r source_dir/*"$pat"* target_dir/ 2>/dev/null; done
首先将所有,
内容转换file.csv
为换行符:
$ tr , '\n' < file.csv
32150129
AAA0616938
32140203
AAA3891784
32140204
AAA0617237
32140205
AAA0617261
32140206
AAA0617285
然后,我们将每个模式读入变量$pat
,然后盲目地将source_dir/*$pat*
(即source_dir/
匹配中的任何内容$pat
)复制到目标目录。如果没有匹配,则不会复制任何内容,并且我们会收到一条错误消息,我们可以使用 丢弃该消息2>/dev/null
。
对于更复杂的方法,你可以做这样的事情:
## make sure we don't match the glob pattern itself when no matching
## directories are found
shopt -s nullglob
mainTargetDir=/path/to/Main_directory
sourceDir=/path/to/start
while IFS=, read -r f1 f2; do
sourceFiles=("$sourceDir"/*"$f1"* "$sourceDir"/*"$f2"*)
[ -z "${sourceFiles[@]}" ] ||
cp -r -- "${sourceFiles[@]}" $mainTargetDir
done < file.csv